【问题标题】:Difference between C++11 std::bind and boost::bindC++11 std::bind 和 boost::bind 的区别
【发布时间】:2012-05-20 07:09:54
【问题描述】:

这两者有什么区别吗?或者我是否可以安全地将代码中每次出现的boost::bind 替换为std::bind,从而消除对Boost 的依赖?

【问题讨论】:

  • 我相信 std::bind 在 C++11 出现时几乎是从 boost::bind 复制而来的,还有很多其他的东西。
  • 问题是关于“相当多”的部分。对于从 Boost 中提取的一些内容,进行了细微的更改。

标签: c++ c++11 boost boost-bind stdbind


【解决方案1】:
  • boost::bindhas overloaded relational operatorsstd::bind 没有。

  • boost::bind supports non-default calling conventions, std::bind 不保证(标准库实现可能提供此作为扩展)。

  • boost::bind 提供了一种直接机制,可以防止对嵌套绑定表达式 (boost::protect) 进行急切求值,std::bind 则不能。 (也就是说,如果他们愿意,可以使用 boost::protectstd::bind,或者自己简单地重新实现它。)

  • std::bind 提供了一种直接机制,允许将任何用户定义的仿函数视为嵌套绑定表达式,以便强制急切求值 (std::is_bind_expression: [func.bind. isbind]/1, [func.bind.bind]/10), boost::bind 没有。

【讨论】:

    【解决方案2】:

    除了其他答案中引用的几个差异之外,还有另外两个差异:

    • boost::bind 似乎在某些情况下处理重载的函数名称,而 std::bind 并没有以相同的方式处理它们。见c++11 faq

    (使用 gcc 4.7.2,boost lib 版本 1_54)

    void foo(){}
    void foo(int i){}
    
    auto badstd1 = std::bind(foo);  
    //compile error: no matching function for call to bind(<unresolved overloaded function type>)
    auto badstd2 = std::bind(foo, 1); 
    //compile error: no matching function for call to bind(<unresolved overloaded function type>)
    auto std1 = std::bind(static_cast<void(*)()>(foo)); //compiles ok
    auto std2 = std::bind(static_cast<void(*)(int)>(foo), 1); //compiles ok
    auto boost1 = boost::bind(foo, 1); //compiles ok
    auto boost2 = boost::bind(foo); //compiles ok
    

    因此,如果您只是将所有 boost::bind 替换为 std::bind,您的构建可能会中断。

    • std::bind 可以无缝绑定到 c++11 lambda 类型,而从 boost 1.54 开始的 boost::bind 似乎需要用户输入(除非定义了 return_type)。见boost doc

    (使用 gcc 4.7.2,boost lib 版本 1_54)

    auto fun = [](int i) { return i;};
    auto stdbound = std::bind(fun, std::placeholders::_1);
    stdbound(1);
    
    auto boostboundNaive = boost::bind(fun, _1);  //compile error.
    // error: no type named ‘result_type’ ...
    auto boostbound1 = boost::bind<int>(fun, _1); //ok
    boostbound1(1);
    auto boostbound2 = boost::bind(boost::type<int>(), fun, _1); //ok
    boostbound2(1);
    

    因此,如果您只是将所有 std::bind 替换为 boost::bind,您的构建也可能会中断。

    【讨论】:

      【解决方案3】:

      除了上面列出的之外,boost::bind 还有一个重要的扩展点:get_pointer() 函数,它允许将 boost::bind 与任何智能指针集成,例如。 ATL::CComPtr 等 http://www.boost.org/doc/libs/1_49_0/libs/bind/mem_fn.html#get_pointer

      因此,使用 boost::bind 你也可以绑定一个weak_ptr: http://lists.boost.org/Archives/boost/2012/01/189529.php

      【讨论】:

      • 标准中的INVOKE 功能适用于任何支持operator* 的智能指针
      【解决方案4】:

      我没有完整的答案,但std::bind 将使用可变参数模板而不是参数列表。

      占位符在std::placeholders 中,就像在std::placeholders::_1 中一样,而不是在全局命名空间中。

      我将命名空间别名为 stdph

      namespace stdph=std::placeholders;
      

      除此之外,我在更新到 C++11 时没有遇到任何问题

      【讨论】:

      • 移植使用占位符的现有 boost::bind 代码时,添加“using namespace std::placeholders;”文件顶部的占位符放入全局命名空间。非常方便。
      • 问题是,在移植时,您通常会以 boost bind 结束,但仍然在争吵;不知何故,您最终会得到标准和 boost 占位符。
      • 这取决于我猜的项目。我用 sed 从一个体面的大小项目中机械地删除了我所有的 boost function.hpp 和 bind.hpp ,并且上面的命名空间指令运行良好。如果您在某些无法更改的标头中有增强绑定,我知道事情会变得丑陋。
      • @goertzenator :我认为问题更多在于使用任何 other Boost 库,因为我敢打赌,至少有三分之一的 Boost 直接或间接使用 boost::bind .
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-04
      • 2020-08-10
      • 1970-01-01
      相关资源
      最近更新 更多