calling a member function of a map iterator

I have a map<int,c*> and I would like to call a member function of the c* and provide a parameter to it. struct c{void f(char*){}}; typedef std::map<int,c*> TMap; TMap a; std::for_each(a.begin(),a.end(),boost::bind(&c::f,boost::bind(&TMap::value_type::second,_1)),NULL); I get "error C2091: function returns function" This is what I would like to replace with the for_each algorithm: for(TMap::iterator i=a.begin();i!=a.end();++i)(*i)->f(NULL); Thanks. -- Regards, Alexander. http://sjcomp.com

Alexander Shyrokov wrote:
I have a map<int,c*> and I would like to call a member function of the c* and provide a parameter to it.
struct c{void f(char*){}}; typedef std::map<int,c*> TMap; TMap a; std::for_each(a.begin(),a.end(),boost::bind(&c::f,boost::bind(&TMap::value_type::second,_1)),NULL);
You have std::for_each( a.begin(), a.end(), boost::bind( &c::f, boost::bind( &TMap::value_type::second, _1 ) ), NULL ); but you need std::for_each( a.begin(), a.end(), boost::bind( &c::f, boost::bind( &TMap::value_type::second, _1 ), NULL ) );

std::for_each( a.begin(), a.end(),
boost::bind( &c::f, boost::bind( &TMap::value_type::second, _1 ), NULL ) ); Indentation does help with these things. But this still does not work I am getting:
boost_1_33_1\boost\bind.hpp(286) : error C2664: 'R boost::_mfi::mf1<R,T,A1>::operator ()<boost::_bi::result_traits<c,F>::type>(U & ,A1) const' : cannot convert parameter 2 from 'int' to 'boost::_bi::result_traits<R,F>::type & ' -- Regards, Alexander. http://sjcomp.com

Alexander Shyrokov wrote:
std::for_each( a.begin(), a.end(),
boost::bind( &c::f, boost::bind( &TMap::value_type::second, _1 ), NULL ) ); Indentation does help with these things. But this still does not work I am getting:
boost_1_33_1\boost\bind.hpp(286) : error C2664: 'R boost::_mfi::mf1<R,T,A1>::operator ()<boost::_bi::result_traits<c,F>::type>(U & ,A1) const' : cannot convert parameter 2 from 'int' to 'boost::_bi::result_traits<R,F>::type & '
The problem here is that NULL is defined as 0, which is of type int. The literal 0 is implicitly convertible to any pointer type, but an int that happens to have the value 0 is not. So you need to cast the NULL to the correct pointer type first. Annoying, I know. There is a proposal for a nullptr keyword that will - hopefully - allow the above code to work as-is. In such a situation I tend to define my own nullptr: struct nullptr_t { template<class T> operator T* () const { return 0; } } nullptr; and use that instead of NULL.

In such a situation I tend to define my own nullptr:
struct nullptr_t { template<class T> operator T* () const { return 0; } } nullptr;
and use that instead of NULL. Thanks, Peter. Both casting and nullptr worked fine. But it brings me to a bigger question, should I bother replacing this code:
struct c{void f(char*){}}; typedef std::map<int,c*> TMap; TMap a; for(TMap::iterator i=a.begin();i!=a.end();++i)(*a)->second.f(NULL): with the more complex code like this: struct c{void f(char*){}}; struct nullptr_t{template<class T>operator T*()const{return 0;}}nullptr; typedef std::map<int,c*> TMap; TMap a; std::for_each(a.begin(),a.end(), boost::bind(&c::f, boost::bind(&TMap::value_type::second,_1), nullptr) ); I know there should be a line. But I am new to the algorithm's way :) Thanks. -- Regards, Alexander. http://sjcomp.com

Alexander Shyrokov wrote:
In such a situation I tend to define my own nullptr:
struct nullptr_t { template<class T> operator T* () const { return 0; } } nullptr;
and use that instead of NULL. Thanks, Peter. Both casting and nullptr worked fine. But it brings me to a bigger question, should I bother replacing this code:
struct c{void f(char*){}}; typedef std::map<int,c*> TMap; TMap a; for(TMap::iterator i=a.begin();i!=a.end();++i)(*a)->second.f(NULL):
with the more complex code like this:
struct c{void f(char*){}}; struct nullptr_t{template<class T>operator T*()const{return 0;}}nullptr; typedef std::map<int,c*> TMap; TMap a; std::for_each(a.begin(),a.end(), boost::bind(&c::f, boost::bind(&TMap::value_type::second,_1), nullptr) );
I know there should be a line. But I am new to the algorithm's way :)
Good question. I tend to prefer for_each_pair( a.begin(), a.end(), boost::bind( &c::f, _2, nullptr ) ); over the explicit loop, and two nested binds aren't automatically out of the question, but for anything more than that the low-tech approach wins. But this is subjective, and it also depends on who'll be reading the code. I don't include for_each_pair and nullptr as part of the complexity since they are one-time investments that can be reused.
participants (2)
-
Alexander Shyrokov
-
Peter Dimov