Sometimes I tend to write functors, not for the sake of maintaining state between function calls, but because I want to capture some arguments that are shared between function calls. As an example:
class SuperComplexAlgorithm
{
public:
SuperComplexAlgorithm( unsigned int x, unsigned int y, unsigned int z )
: x_( x ), y_( y ), z_( z )
{}
unsigned int operator()( unsigned int arg ) const /* yes, const! */
{
return x_ * arg * arg + y_ * arg + z_;
}
private:
// Lots of parameters are stored as member variables.
unsigned int x_, y_, z_;
};
// At the call site:
SuperComplexAlgorithm a( 3, 4, 5 );
for( unsigned int i = 0; i < 100; ++i )
do_stuff_with( a ); // or whatever
Compared to
unsigned int superComplexAlgorithm( unsigned int x, unsigned int y,
unsigned int z, unsigned int arg )
{
return x * arg * arg + y * arg + z;
}
// At the call site:
auto a = std::bind( superComplexAlgorithm, 3, 4, 5, std::placeholders::_1 );
for( unsigned int i = 0; i < 100; ++i )
do_stuff_with( a );
the first solution has a lot of drawbacks, in my opinion:
x
, y
, z
do is split at different places (constructor, class definition, operator()
).Yes, I just realized how useful boost::bind
or std::bind
can be. Now for my question before I start using this in a lot of my code: Is there any situation where I should consider using a hand-written stateless functor over binding arguments in a plain function?
The lambda solution would be the idomatic C++11 way:
auto a = [&]( int x ){ return superComplexAlgorithm( 3, 4, 5, x ); };
for( unsigned int i = 0; i < 100; ++i )
do_stuff_with( a );
The advantage of using a hand written functor is that you can:
bind
)auto
) -- the same is true of bind
, but it also has a non-anonymous meaningful type you can get at without decltype
ing the entire expression! C++1y again makes this better for bind
/lambda.bind
does this)You can also do some extremely powerful things with hand written functors that are impossible to do with bind
and lambdas, like wrap an overload set of multiple functions into one object (that may or may not share a name), but that kind of corner case isn't going to show up often.
Is there any situation where I should consider using a hand-written stateless functor over binding arguments in a plain function?
From the comments:
I don't want to define superComplexAlgorithm at the call site, because it is super complex, is used in many places, needs testing and documentation, etc..
If the implementation of superComplexAlgorithm
requires a bunch of code and you end up splitting it into different functions that take a large amount of arguments, then you might be better off with a class that provides the shared state across the internal implementation functions. Other that that corner case, the behavior of std::bind
would be equivalent to the functor you provided in the question.
Some notes, since you mention boost::bind
and std::bind
as alternatives. You might want to test what your implementation does. For example, with boost 1.35 (ancient) the bind
operation would make 4 copies of each argument, VS2010 would make 7 copies in std::bind
although std::bind
in gcc 4.7 did only 1. If the arguments are small that won't make up to a high cost, but if you are doing the operation or your objects are expensive to copy... just measure.
Regarding the lambda, if performance is an issue, also measure how it behaves. It should make a single copy. If performance is not an issue, then a lambda is far less explicit on what is being captured (the user needs to read the implementation of the lambda to figure that out), and even looking at the code it might not be that obvious.
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