【问题标题】:How to use boost bind with a member function如何将 boost 绑定与成员函数一起使用
【发布时间】:2011-01-19 05:44:03
【问题描述】:

以下代码导致 cl.exe 崩溃 (MS VS2005)。
我正在尝试使用 boost bind 来创建一个调用 myclass 方法的函数:

#include "stdafx.h"
#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <functional>

class myclass {
public:
    void fun1()       { printf("fun1()\n");      }
    void fun2(int i)  { printf("fun2(%d)\n", i); }

    void testit() {
        boost::function<void ()>    f1( boost::bind( &myclass::fun1, this ) );
        boost::function<void (int)> f2( boost::bind( &myclass::fun2, this ) ); //fails

        f1();
        f2(111);
    }
};

int main(int argc, char* argv[]) {
    myclass mc;
    mc.testit();
    return 0;
}

我做错了什么?

【问题讨论】:

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


    【解决方案1】:

    改用以下内容:

    boost::function<void (int)> f2( boost::bind( &myclass::fun2, this, _1 ) );
    

    这会将传递给函数对象的第一个参数转发给使用占位符的函数 - 您必须告诉 Boost.Bind 如何处理参数。使用您的表达式,它会尝试将其解释为不带参数的成员函数。
    参见例如herehere 了解常见的使用模式。

    请注意,VC8s cl.exe 经常因 Boost.Bind 误用而崩溃 - 如果有疑问,请使用带有 gcc 的测试用例,您可能会得到很好的提示,例如模板参数 Bind-internals 被实例化,如果你通读输出。

    【讨论】:

    • 你有没有机会帮忙解决这个stackoverflow.com/questions/13074756/…?它很相似,但std::function 给出了一个错误
    • 谢谢你,这有点令人困惑,但你的回答救了我的培根!
    【解决方案2】:

    Boost.Bind 是一个库,它简化并概括了最初需要 std::bind1st()std::bind2nd() 的功能>

    示例 1.1:std::for_each() 具有兼容函数

    #include <vector>
    #include <algorithm>
    #include <iostream>
    
    void print(int i)
    {
      std::cout << i << '\n';
    }
    
    int main()
    {
      std::vector<int> v{1, 3, 2};
      std::for_each(v.begin(), v.end(), print);
    }
    

    std::for_each() 的第三个参数是一个函数或函数对象,它需要一个唯一的参数。在示例 1.1 中,std::for_each() 将容器 v 中的数字作为唯一参数一个接一个地传递给 print()。

    如果你需要传入一个签名不符合算法要求的函数,那就更难了。例如,如果您希望 print() 接受输出流作为附加参数,则不能再将其与 std::for_each() 一起使用。

    示例 1.2。 std::for_each()std::bind1st()

    #include <vector>
    #include <algorithm>
    #include <functional>
    #include <iostream>
    
    class print : public std::binary_function<std::ostream*, int, void>
    {
    public:
      void operator()(std::ostream *os, int i) const
      {
        *os << i << '\n';
      }
    };
    
    int main()
    {
      std::vector<int> v{1, 3, 2};
      std::for_each(v.begin(), v.end(), std::bind1st(print{}, &std::cout));
    }
    

    示例 1.1 一样,示例 1.2 将 v 中的所有数字写入标准输出。但是,这一次,输出流作为参数传递给 print()。为此,函数 print() 被定义为从 std::binary_function 派生的函数对象。

    使用 Boost.Bind,您无需将 print() 从函数转换为函数对象。相反,您使用函数模板 boost::bind(),它在 boost/bind.hpp 中定义。

    示例 1.3:std::for_each()boost::bind()

    #include <boost/bind.hpp>
    #include <vector>
    #include <algorithm>
    #include <iostream>
    
    void print(std::ostream *os, int i)
    {
      *os << i << '\n';
    }
    
    int main()
    {
      std::vector<int> v{1, 3, 2};
      std::for_each(v.begin(), v.end(), boost::bind(print, &std::cout, _1));
    }
    

    示例 1.3 将 print() 用作函数,而不是函数对象。因为 print() 需要两个参数,所以函数不能直接传递给 std::for_each()。相反,boost::bind() 被传递给 std::for_each() 并且 print() 作为第一个参数被传递给 boost::bind( ).

    由于 print() 需要两个参数,所以这两个参数也必须传递给 boost::bind()。它们是指向 std::cout_1 的指针。

    _1 是一个占位符。 Boost.Bind 定义了从 _1_9 的占位符。这些占位符告诉 boost::bind() 返回一个函数对象,该对象期望与具有最大数量的占位符一样多的参数。如果像 Example 1.3 中那样,只使用占位符 _1boost::bind() 返回一个一元函数对象——一个函数对象需要一个唯一的参数。在这种情况下这是必需的,因为 std::for_each() 只传递一个参数。

    std::for_each() 调用一元函数对象。传递给函数对象的值——来自容器 v 的数字——占据占位符 _1 的位置。 boost::bind() 获取数字和指向 std::cout 的指针并将它们转发给 print()。

    请注意,boost::bind()std::bind1st()std::bind2nd() 一样,需要按值参数。为了防止调用程序尝试复制 std::cout,print() 需要一个指向流的指针。 Boost.Ref 提供了一个函数,允许您通过引用传递参数。

    示例 1.4 说明了如何使用 boost::bind() 定义二进制函数对象。它使用算法std::sort(),它需要一个二进制函数作为它的第三个参数。

    示例 1.4std::sort()boost::bind()

    #include <boost/bind.hpp>
    #include <vector>
    #include <algorithm>
    #include <iostream>
    
    bool compare(int i, int j)
    {
      return i > j;
    }
    
    int main()
    {
      std::vector<int> v{1, 3, 2};
      std::sort(v.begin(), v.end(), boost::bind(compare, _1, _2));
      for (int i : v)
        std::cout << i << '\n';
    }
    

    示例 1.4 中,由于使用了占位符 _2,因此创建了一个二进制函数对象。 std::sort() 算法使用容器 v 中的两个值调用此二进制函数对象,并计算返回值以对容器进行排序。函数 compare() 被定义为按降序对 v 进行排序。

    由于compare()是二元函数,可以直接传给std::sort()。但是,使用 boost::bind() 仍然有意义,因为它可以让您更改参数的顺序。例如,如果您想按升序对容器进行排序但不想更改 compare(),则可以使用 boost::bind()

    示例 1.5std::sort()boost::bind() 并改变了占位符的顺序

    #include <boost/bind.hpp>
    #include <vector>
    #include <algorithm>
    #include <iostream>
    
    bool compare(int i, int j)
    {
      return i > j;
    }
    
    int main()
    {
      std::vector<int> v{1, 3, 2};
      std::sort(v.begin(), v.end(), boost::bind(compare, _2, _1));
      for (int i : v)
        std::cout << i << '\n';
    }
    

    【讨论】:

      【解决方案3】:

      以下对我有用。

      class test_component
      {
      private:
          void on_wait_complete(const int i);
      };
      
      void test_component::on_wait_complete (const int i)
      {
          cout << "on_wait_complete was called" << endl;
      
          return;
      }
      
      int main()
      {
          // timerPtr_ is a variable declared in class test_component.
          timerPtr_->async_wait(boost::bind(&test_component::on_wait_complete, this, _1));
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-09-14
        • 2011-06-23
        • 1970-01-01
        • 1970-01-01
        • 2016-02-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多