Now I am try to use boost bind & mem_fn
.
But there's a problem to bind overloaded-function.
How to resolve compile error of follow codes?
boost::function< void( IF_MAP::iterator ) > bmf = std::mem_fun1< void, IF_MAP, IF_MAP::iterator >( &IF_MAP::erase );
boost::function< void( IF_MAP::iterator ) > bmf = boost::mem_fn< void, IF_MAP, IF_MAP::iterator >( &IF_MAP::erase );
The main purpose is to compile follow codes
IF_MAP M;
boost::function< void( IF_MAP::iterator ) > bmf = boost::bind(
boost::mem_fn< void, IF_MAP, IF_MAP::iterator >( &IF_MAP::erase ),
&M, _1 );
M.insert( IF_MAP::value_type( 1, 1.f ) ); M.insert( IF_MAP::value_type( 2, 2.f ) );
bmf( 2 );
The compile error messages are like this...
error C2665: 'boost::mem_fn' : none of the 2 overloads could convert all the argument types could be 'boost::_mfi::mf1 boost::mem_fn::iterator>(R (__thiscall std::map<_Kty,_Ty>::* )(A1))' or 'boost::_mfi::cmf1 boost::mem_fn::iterator>(R (__thiscall std::map<_Kty,_Ty>::* )(A1) const)'
P.S. As U know, std::map has 3 overloaded erase member function
void erase(iterator _Where)
size_type erase(const key_type& _Keyval)
void erase(iterator _First, iterator _Last)
2nd function can be binded easily, but others not.Edit
To describe my question in more detail:
Actually, I want to make deferred function call. When I meet return code of function, then it's time to scope out, so deferred function should be called.
Now I am refactoring some legacy codes. Nowdays, I usually see like this pattern of codes.
(Actual codes are more complex but almost same as follows)
Duplicated erase()
calls are scattered in this function.
typedef map< int, float > IF_MAP;
bool DoAndPopOld( IF_MAP& M, int K )
{
IF_MAP::iterator Itr = M.find( K );
if ( Itr == M.end() ) return false;
if ( K < 10 )
{
M.erase( Itr ); // erase call is here...
return false;
}
if ( 100 < K )
{
// Do something
M.erase( Itr ); // and here...
return true;
}
// Do something
M.erase( Itr ); // and also here!
return true;
}
So, I wanna refactoring above code like this...
class ScopedOutCaller
{
private:
boost::function< void() > F;
public:
ScopedOutCaller( boost::function< void() > _F ) : F(_F) {}
~ScopedOutCaller() { F(); } // deferred function call
};
bool DoAndPopNew( IF_MAP& M, int K )
{
IF_MAP::iterator Itr = M.find( K );
if ( Itr == M.end() ) return false;
// Make deferred call, so I do not consider calling erase function anymore.
ScopedOutCaller SOC( boost::bind( &IF_MAP::erase ), &M, Itr );
if ( K < 10 )
{
// M.erase( Itr ); <-- unnecessary
return false;
}
if ( 100 < K )
{
// Do something
// M.erase( Itr ); <-- unnecessary
return true;
}
// Do something
// M.erase( Itr ); <-- unnecessary
return true;
}
But, as I asked... compile errors are occurred. The long and the short of what I want to do is how to defer function call. Please tell me the way to make deferred call. Thanks.
std::map
s member function erase()
is overloaded, thus you have to manually disambiguate - see the Boost.Bind FAQ.
E.g. for the size_type erase(const key_type&)
overload:
typedef IF_MAP::size_type (IF_MAP::*EraseType2)(const IF_MAP::key_type&);
boost::function<void (const IF_MAP::key_type&)> bmf2;
bmf2 = boost::bind((EraseType2)&IF_MAP::erase, &M, _1);
To select the other versions simply change the type you are casting to, e.g.:
// 1. void erase(iterator position) :
typedef void (IF_MAP::*EraseType1)(IF_MAP::iterator);
boost::function<void (IF_MAP::iterator)> bmf1;
bmf1 = boost::bind((EraseType1)&IF_MAP::erase, &M, _1);
// 3. void erase(iterator first, iterator last) :
typedef void (IF_MAP::*EraseType3)(IF_MAP::iterator, IF_MAP::iterator);
boost::function<void (IF_MAP::iterator, IF_MAP::iterator)> bmf3;
bmf3 = boost::bind((EraseType3)&IF_MAP::erase, &M, _1, _2);
Sadly Visual Studio is non-conforming to C++03 here (once again...) and you have to use the following two forms:
typedef IF_MAP::iterator (IF_MAP::*EraseType1)(IF_MAP::const_iterator);
typedef IF_MAP::iterator (IF_MAP::*EraseType3)(IF_MAP::const_iterator,
IF_MAP::const_iterator);
With VC8 and VC9 you can solve that problem by using _HAS_STRICT_CONFORMANCE
, but this breaks again with VC10 as C++0x changes the erase()
overloads to the forms used by Dinkumware (see N3092, 23.4.1).
For portability i'd go for using a wrapper function instead to get around these annoying problems; if however you only care about VC just use the types i provided above.
To execute the resulting functors at block exit, the simplest way is to use Boosts shared_ptr
or a similar scope guard. E.g. for the VC specific cast:
typedef IF_MAP::iterator (IF_MAP::*EraseType)(IF_MAP::const_iterator);
boost::shared_ptr<void> guard(static_cast<void*>(0),
boost::bind((EraseType)&IF_MAP::erase, &M, Itr));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With