Boost logo

Boost Users :

From: ·çÎèÓ°Ìì (snwcwt_at_[hidden])
Date: 2008-06-04 01:22:58


I'm a newbie in boost library and sorry for my poor English.

I have a project now, it was created in Visual Studio.Net 2003 and the version of the boost library is 1.33.1, all thing is good. But, When I replaced the boost library with the new version 1.34.1 or 1.35.0, the project can't compiled correct. The error message is 'can't convert const sometype& to sometype&'. So, i force myself to read the source code of boost library and compare them betwwen version 1.33.1 and version 1.44.1. at last, I found the problem and written a test program. The following code is the test program:

#include "stdafx.h"
#include <boost/bind.hpp>
#include <vector>
#include <algorithm>

struct _sUserData
{
    int m_nUserId;
    int m_nUserAge;
    _sUserData()
        : m_nUserId( rand() )
        , m_nUserAge( rand()%100+1 )
    {
    }
};

void AddUserAge( int& age )
{
    ++age;
}

int _tmain(int argc, _TCHAR* argv[])
{
    std::vector<_sUserData> vUserData;
    for( int i = 0; i < 10; ++i )
        vUserData.push_back( _sUserData() );
    std::for_each( vUserData.begin(), vUserData.end(), boost::bind( AddUserAge, boost::bind( &_sUserData::m_nUserAge, _1 ) ) );
    return 0;
}

If i change the function AddUserAge( int& age ) to AddUserAge( const int& age ), all things is good. but I need change this parameter.

In the version 1.33.1, the data member formal boost::bind function was defined as following:

template<class R, class T, class A1>
_bi::bind_t< R, _mfi::dm<R, T>, typename _bi::list_av_1<A1>::type >
    BOOST_BIND(R T::*f, A1 a1)
{
    typedef _mfi::dm<R, T> F;
    typedef typename _bi::list_av_1<A1>::type list_type;
    return _bi::bind_t<R, F, list_type>( F(f), list_type(a1) );
}

In the version 1.35.0, the boost::bind function was defined as following:

template< class A1, class M, class T >
_bi::bind_t<
    typename _bi::dm_result< M T::*, A1 >::type,
    _mfi::dm<M, T>,
    typename _bi::list_av_1<A1>::type
>

BOOST_BIND( M T::*f, A1 a1 )
{
    typedef typename _bi::dm_result< M T::*, A1 >::type result_type;
    typedef _mfi::dm<M, T> F;
    typedef typename _bi::list_av_1<A1>::type list_type;
    return _bi::bind_t< result_type, F, list_type >( F( f ), list_type( a1 ) );
}

Although the code that is similar to the version 1.33.1 is existed, but it is written in a macro condition, and in my environment is invalid, so ignore it.

The difference is the return type. The boost::_bi::dm_result is defined as following:

namespace _bi
{
    template< class Pm, int I > struct add_cref;

    template< class M, class T > struct add_cref< M T::*, 0 >
    {
        typedef M type;
    };

    template< class M, class T > struct add_cref< M T::*, 1 >
    {
        typedef M const & type;
    };

    template<class R> struct isref
    {
        enum value_type { value = 0 };
    };

    template<class R> struct isref< R& >
    {
        enum value_type { value = 1 };
    };

    template<class R> struct isref< R* >
    {
        enum value_type { value = 1 };
    };

    template<class Pm, class A1> struct dm_result
    {
        typedef typename add_cref< Pm, 1 >::type type;
    };

    template<class Pm, class R, class F, class L> struct dm_result< Pm, bind_t<R, F, L> >
    {
        typedef typename bind_t<R, F, L>::result_type result_type;
        typedef typename add_cref< Pm, isref< result_type >::value >::type type;
    };
}

the compiler will convert the result type to const reference, then pass it to user's function, the error is caught.

Now, all things is come out. But I don't understand why add const reference to the result type and the behavior is difference with the version 1.33.1.

Wait for your answer and thanks for your time, and sorry for my poor in English:)



Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net