【问题标题】:boost::bind() binds extra arguments?boost::bind() 绑定额外的参数?
【发布时间】:2014-03-27 01:01:40
【问题描述】:

boost::bind() 是否绑定额外的参数,因为它似乎将一个没有参数的绑定函数传递给一个期望参数 double 的函数可以正常工作?如果我要显式写出绑定函数,那应该是什么?

struct MyClass
{
    void f() 
    {
        std::cout << "f()" << std::endl;
    }
};

void bar( const boost::function<void(const double&)>& f )
{
    f( 1.0 );
}

int main()
{
    MyClass c;

    // why this compiles
    bar( boost::bind( &MyClass::f, &c ) );

    // what should I write if I want to create the binded function explicitly before pass into bar?
    // boost::function<void(const double&)> f = boost::bind( ... boost::bind( &MyClass::f, &c ), ?? )
    bar( f );

}

【问题讨论】:

    标签: c++ boost boost-bind boost-function


    【解决方案1】:

    这是设计使然,调用绑定表达式时传递的未绑定参数(例如1.0)将被忽略。

    boost::function<void(const double&)> f = boost::bind(&MyClass::f, &c);
    bar(f);
    

    对于绑定表达式的显式赋值会很好。

    更新评论:

    记住,两条准则:

    • function&lt;...&gt; 有固定签名
    • bind 表达式确实没有具有固定签名。 bind 的全部目的是更改签名。这包括例如

      • 添加状态以填充从签名中删除的形式参数或
      • 添加参数,通过不将它们绑定到目标可调用来忽略
      • 使用隐式转换更改参数/返回类型
      • 甚至更改参数绑定到目标可调用对象的顺序,而从技术上讲,签名可以保持不变。

    因此,虽然您不能将不同的func&lt;...&gt; 类型分配给彼此,但您始终可以将bind 一个签名分配给另一个。

    这里有一个更完整的演示,展示了使用functionbind 可以做的限制,以及为什么(它的行为方式):Live On Coliru

    #include <boost/function.hpp>
    #include <boost/bind.hpp>
    #include <iostream>
    #include <cassert>
    
    int foo0()            { return 0; }
    int foo1(int)         { return 1; }
    int foo2(int,int)     { return 2; }
    int foo3(int,int,int) { return 3; }
    
    int main()
    {
        boost::function<int()>            func0;
        boost::function<int(int)>         func1;
        boost::function<int(int,int)>     func2;
        boost::function<int(int,int,int)> func3;
    
        // "straight" assignment ok:
        // -------------------------
        func0 = foo0;                          assert (0 == func0());
        func1 = foo1;                          assert (1 == func1(-1));
        func2 = foo2;                          assert (2 == func2(-1,-1));
        func3 = foo3;                          assert (3 == func3(-1,-1,-1));
    
        // "mixed" assignment not ok:
        // --------------------------
        // func0 = foo1;                       // compile error
        // func3 = foo2;                       // compile error
        // func1 = func2;                      // compile error, just the same
        // func2 = func1;                      // compile error, just the same
    
        // SOLUTION: you can always rebind:
        // --------------------------------
        func0 = boost::bind(foo3, 1, 2, 3);    assert (func0() == 3);
        func3 = boost::bind(foo1, _3);         assert (func3(-1,-1,-1) == 1);
        func3 = boost::bind(foo2, _3, _2);     assert (func3(-1,-1,-1) == 2);
        // same arity, reversed arguments:
        func3 = boost::bind(foo3, _3, _2, _1); assert (func3(-1,-1,-1) == 3);
    
        // can't bind more than number of formal parameters in signature:
        // --------------------------------------------------------------
        // func3 = boost::bind(foo1, _4);      // in fact, the bind is fine, but assigning to `func3` fails
    }
    

    所有断言都通过。当你取消注释不编译的行时,你可以尝试编译器所说的内容。

    干杯

    【讨论】:

    • @seha - 额外的参数在哪里? MyClass::f 有 0 个参数。当 boost::bind(&MyClass::f, &c) 被赋值给 boost::function 时,是否在 boost::function assign 中绑定了另一个 double 类型的额外参数??
    • @Surfcode, MyClass::f 有一个参数 (this),这是您在绑定表达式中绑定到 &amp;c 的参数。现在,在bar(并通过boost::function&lt;&gt; 实例)中,您传递了一个extra 参数(1.0,就像我提到的那样),它没有被绑定并且因此被忽略。
    • 抱歉问了一个延迟的问题:而不是 adapt = bind(&bar, _1, _3);我该怎么做: function adapt2 = bind(&bar, _1, _3); // 适应 = 适应 2 ??因为我想在分配适应之前传递adapter2(作为参数类型)。所以,不能直接赋值 bind(...) 去适配。
    • @surfcode 我已经重写了回答你问题的解释。慢慢读吧。我认为penny will drop。有一个更广泛的示例演示了哪些有效,哪些无效,为什么以及如何表现。干杯。
    猜你喜欢
    • 1970-01-01
    • 2010-10-02
    • 1970-01-01
    • 2018-05-13
    • 1970-01-01
    • 2011-05-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多