【问题标题】:Is it possible to use boost::bind to effectively concatenate functions?是否可以使用 boost::bind 来有效地连接函数?
【发布时间】:2010-04-29 21:14:25
【问题描述】:

假设我有一个 boost::function ,它带有一个名为CallbackType 的任意签名。

  • 是否可以使用boost::bind 组成一个函数,该函数采用与 CallbackType 相同的参数但连续调用两个函子?

我对任何可能的解决方案持开放态度,但这里有一个...

...使用一些magic 模板的假设示例:

Template<typename CallbackType>
class MyClass
{
    public:
        CallbackType doBoth;

        MyClass( CallbackType callback )
        {
            doBoth = bind( magic<CallbackType>, 
                             protect( bind(&MyClass::alert, this) ),   
                               protect( callback )                    );
        }

        void alert()
        {
            cout << "It has been called\n";
        }
};

void doIt( int a, int b, int c)
{
    cout << "Doing it!" << a << b << c << "\n";
}

int main()
{
    typedef boost::function<void (int, int, int)> CallbackType;

    MyClass<CallbackType> object( boost::bind(doIt) );

    object.doBoth();

    return 0;
}

【问题讨论】:

  • magic 是否应该按照bind 来实现? bind 的作用是什么?当然,您实际上并没有将任何内容绑定到回调。
  • magic 可能是一些模板,它会自动创建一个函子,该函子将两个函子作为参数 + CallbackType 的所有参数......但这只是为了说明我的目标,而不是必须提供一个现实的解决方案。我愿意接受截然不同的建议。
  • 您是否尝试将void (void)void (int, int, int) 组合在一起?或者这只是一个错字?
  • 不,这是正确的......只是问题的另一个复杂性。模板无法提前知道 sig 是什么,因此无法使 alert 匹配它。
  • 您能否通过一个具体而简单的示例(没有绑定)清楚地说明您想要实现的组合是什么?考虑到当一个函数的结果是另一个函数的输入时,函数组合是有意义的。

标签: c++ boost callback bind functor


【解决方案1】:

Boost 已经提供了一种创建绑定函数序列的方法。使用Lambda's comma operator

using namespace boost::lambda;
MyClass mc;
CallbackType object = (bind(&MyClass::alert, mc), bind(doIt, _1, _2, _3));
object(1, 2, 3);

这将创建一个新的仿函数object。当您使用三个参数调用该函子时,它将依次调用mc.alert(),然后将这些参数传递给doIt。括号很重要。

要使上面的示例正常工作,您需要 alert 成为 const 函数。如果它需要非常量,则将 指针 传递给mc,或者用boost::ref(mc) 包装它。您需要使用 Boost.Lambda 的 bind 而不是 Boost.Bind 的;后者与 Lambda 的函数组合运算符(尤其是逗号)不兼容。

【讨论】:

    【解决方案2】:
    template< class Callback >
    struct pre_caller {
        Callback c;
    
        pre_caller( Callback in_c ) : c( in_c ) {}
    
        void alert() {} // or an instance of a functor
    
        operator()
        { alert(); c(); }
    
        template< class T1 >
        operator( T1 a ) // not sure if/what qualification to add to a
        { alert(); c( a ); } // or whether to attempt to obtain from
                             // function_traits<Callback>?
        template< class T1, class T2 >
        operator( T1 a, T2 b )
        { alert(); c( a, b ); }
    
        template< class T1, class T2, class T3 >
        operator( T1 a, T2 b, T3 c )
        { alert(); c( a, b, c ); }
    
        // ad nauseam... and I mean nausea, maybe read up on Boost Preprocessor.
    };
    

    Boost Bind 对其可变参数 voodoo 使用了大量的预处理器黑客攻击,不幸的是,我认为它并没有提供本质上就是这样的头部修补模式或工具。

    【讨论】:

    • 似乎应该有一个更简单的方法,也许我的稻草人示例完全错误。开始赏金,但这可能最终被标记为答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-12
    • 2014-06-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多