We're transitioning to C++11 but still a few months away. Please feel free to give C++11 responses, but we're curious whether there's a non-ugly way to do it in C++98/03.
A co-worker came to me with code resembling:
typedef void(B::*fptr_t)();
void A::my_foreach( uint idx, fptr_t fptr ) {
for( iter_type iter = asdf[idx].begin(); iter != asdf[idx].end(); ++iter )
iter->second->*fptr();
}
void A::get( uint idx ) { my_foreach( idx, &B::get ); }
void A::get( uint idx ) { my_foreach( idx, &B::get ); }
... asking if there was a better way, to which I responded with:
void A::get( uint idx ) {
std::for_each( asdf[idx].begin()
, asdf[idx].end()
, boost::bind( &B::get, _1 ) );
}
void A::put( uint idx ) {
std::for_each( asdf[idx].begin()
, asdf[idx].end()
, boost::bind( &B::put, _1 ) );
}
... but that still left me feeling like more could be done to avoid code duplication. The general solutions that have occurred to me are:
- Re-factor the code so the involved classes have less responsibilities, and wrap the container(s) in decorator/proxy objects that provide some of the needed functionality.
- Generic
apply to my container
member function that takes the intended function as an argument (that is, callers must provide the function) - Make two private member functions: the function mentioned in (2) and one to return a functor to call it, then public functor objects initialized in the constructor.
- Use
boost::bind
to wrap the whole thing, making a functor that could be used like this:
.
functor_t get = my_binder( &B::get );
functor_t put = my_binder( &B::put );
... where my_binder
would produce an object that can perform the same operations, but that quickly got ugly because of how many functions are actually executing in the above code (operator[]
, X::begin
, X::end
, something for applying the function ptr to each element of the container
).
Is there another/better way prior to C++11, or are those solutions pretty much what's available?