Functor与std :: bind

Mar*_*ayr 4 c++ boost-bind c++11

有时我倾向于编写仿函数,而不是为了在函数调用之间维护状态,而是因为我想捕获函数调用之间共享的一些参数.举个例子:

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
Run Code Online (Sandbox Code Playgroud)

相比

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 );
Run Code Online (Sandbox Code Playgroud)

在我看来,第一种解决方案有很多缺点:

  • 什么文件x,y,z做的是在不同的地方(构造函数,类定义,拆分operator()).
  • 大量的锅炉板代码.
  • 不太灵活.如果我想捕获不同的参数子集怎么办?

是的,我刚刚意识到有用boost::bindstd::bind可能.现在我的问题在我开始在很多代码中使用它之前:是否有任何情况我应该考虑在普通函数中使用手写无状态函数来绑定参数?

Yak*_*ont 8

lambda解决方案将是idomatic C++ 11方式:

auto a = [&]( int x ){ return superComplexAlgorithm( 3, 4, 5, x ); };
for( unsigned int i = 0; i < 100; ++i )
  do_stuff_with( a );
Run Code Online (Sandbox Code Playgroud)

使用手写仿函数的优点是,您可以:

  1. 将参数移动到捕获中,或者转换它们(你可以用C++ 1y中的lambda做到这一点,但还没有 - 这也是可能的bind)
  2. 它具有非匿名类型(所以你可以谈论的类型,而无需使用auto) -同样是真实bind的,但它也有一个非匿名有意义的类型,你可以在无需得到decltype荷兰国际集团整个表达式!C++ 1y再次为bind/ lambda 做得更好.
  3. 你可以完美地转发剩下的参数(你可以在C++ 1y中用lambda bind做到这一点,并且这样做)
  4. 你可以搞乱捕获数据的存储方式(在指针中?一个智能指针?),而不会弄乱你创建实例的代码.

你也可以做一些与手写函子是不可能做的非常强大的东西bind和lambda表达式,比如包装功能的复合型重载集合到一个对象(可以或不可以共享名),但那种极端情况ISN的不经常出现.

  • 如果要模拟`bind`,请使用复制捕获. (5认同)