A question about boost::bind function

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:)

Not sure why this was changed, though I've never used bind in this way (specifically, to bind to a reference of a member variable). Are you free to make changes to the code? This should work in either version: void AddUserAge( _sUserData& d ) { // <-- change this to a reference to the struct ++d.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, _1 )); // <-- and remove the inner bind return 0; } Or you could just do this in 1.34.0 or higher: #include <boost/foreach.hpp> .... int _tmain(int argc, _TCHAR* argv[]) { std::vector<_sUserData> vUserData( 10 ); // vector of 10 _sUserData, default constructed BOOST_FOREACH( _sUserData& d, vUserData ) ++d.age; return 0; } Of course, all this is starting to look like a homework problem to me... 2008/6/3 风舞影天 <snwcwt@qq.com>:
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.

This isn't my desired answer, but thank you for your answer, however. ----- Original Message ----- From: Oliver Seiler Newsgroups: gmane.comp.lib.boost.user To: boost-users@lists.boost.org Sent: Thursday, June 05, 2008 4:12 AM Subject: Re: A question about boost::bind function Not sure why this was changed, though I've never used bind in this way (specifically, to bind to a reference of a member variable). Are you free to make changes to the code? This should work in either version: void AddUserAge( _sUserData& d ) { // <-- change this to a reference to the struct ++d.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, _1 )); // <-- and remove the inner bind return 0; } Or you could just do this in 1.34.0 or higher: #include <boost/foreach.hpp> .... int _tmain(int argc, _TCHAR* argv[]) { std::vector<_sUserData> vUserData( 10 ); // vector of 10 _sUserData, default constructed BOOST_FOREACH( _sUserData& d, vUserData ) ++d.age; return 0; } Of course, all this is starting to look like a homework problem to me... 2008/6/3 风舞影天 <snwcwt@qq.com>: 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. ------------------------------------------------------------------------------ _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

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; }
This compiles in 1.33, but doesn't actually increment the age; the inner bind returns a temporary int by value, and the outer bind increments that. Can you please try boost::bind<int&>( &_sUserData::m_nUserAge, _1 ) and see if it helps?

Thank you for your answer. boost::bind<int&>( &_sUserData::m_nUserAge, _1 ) is work good. ----- Original Message ----- From: "Peter Dimov" <pdimov@pdimov.com> Newsgroups: gmane.comp.lib.boost.user To: <boost-users@lists.boost.org> Sent: Thursday, June 05, 2008 4:33 AM Subject: Re: A question about boost::bind function
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; }
This compiles in 1.33, but doesn't actually increment the age; the inner bind returns a temporary int by value, and the outer bind increments that.
Can you please try boost::bind<int&>( &_sUserData::m_nUserAge, _1 ) and see if it helps?
--------------------------------------------------------------------------------
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
participants (4)
-
Oliver Seiler
-
Peter Dimov
-
风舞影天
-
风舞影天(Rubiphisto)