【问题标题】:No matching call error occuring for boost::ref but not with std::refboost::ref 没有发生匹配的调用错误,但 std::ref 没有发生匹配的调用错误
【发布时间】:2013-02-25 18:47:33
【问题描述】:

我编写了一些代码,这些代码使用函子以及来自 boost::std::(对于 C++11)命名空间的 refbind 模板计算向量的元素数量。我使用#defineboost::std:: 命名空间之间切换。我使用的是 boost 1.53 版本,我的编译命令是g++ test.cpp -std=c++11。我尝试使用 gcc 版本 4.7.2 和 4.6.3,但两者都出现相同的错误。

我有 3 个问题:

  1. 我不理解为示例 2 生成的错误。
  2. 是否可以仅通过切换命名空间来使这样的代码具有可移植性?
  3. 是否有详细描述bindreffunctionstdboost 版本之间差异的良好参考? (我看到this 的问题,但答案没有提到reffunction

谢谢!

附:这个例子只是说明了我的问题,我知道size() for std::vector :-)

//#define USE_STD

#ifdef USE_STD
#include <functional>
using namespace std::placeholders;
namespace impl = std;
#else
#include <boost/version.hpp>
#include <boost/bind.hpp>
#include <boost/ref.hpp>
namespace impl = boost;
#endif

#include <iostream>
#include <algorithm>
#include <vector>

class Item {
    int id_;

public:
    Item(int id) : id_(id) {};
};

template <typename ITEM>
class Counter {
    int count_;

public:
    // typedef void result_type; // adding this fixes Example 3 when impl=boost
    Counter() : count_(0) {};
    void operator()(ITEM* item) {count_++;}
    int operator()() {return count_;}
};

//------------------------------------------------------------------------------
int main(int argc, char *argv[])
{
#ifndef USE_STD
    std::cout << "BOOST_LIB_VERSION=" << BOOST_LIB_VERSION << std::endl;
#endif

    // allocate
    typedef std::vector<Item*> ItemVec;
    ItemVec vec;
    for (int i = 0; i < 9; ++i) {vec.push_back(new Item(i));}

    // Example 1, works for BOTH
    Counter<Item> f1;
    f1 = std::for_each(vec.begin(), vec.end(), f1);
    std::cout << "f1()=" << f1() << std::endl;

    // Example 2, works with impl=std ONLY
    // COMPILE ERROR with impl=boost: "no match for call to ‘(boost::reference_wrapper<Counter<Item> >) (Item*&)’"
    Counter<Item> f2;
    std::for_each(vec.begin(), vec.end(), impl::ref(f2));
    std::cout << "f2()=" <<  f2() << std::endl;

    // Example 3, works with impl=std ONLY
    // COMPILE ERROR with impl=boost "no type named ‘result_type’ in ‘class Counter<Item>’"
    // this can fixed by adding the typedef described above
    Counter<Item> f3;
    std::for_each(vec.begin(), vec.end(), impl::bind(impl::ref(f3), _1));
    std::cout << "f3()=" << f3() << std::endl;

    // clean up
    for (ItemVec::iterator it = vec.begin(); it != vec.end(); ++it) {
        delete *it;
    }
    vec.clear();

    return 0;
}

【问题讨论】:

    标签: c++ c++11 boost boost-ref


    【解决方案1】:

    示例 2 失败,因为 boost::reference_wrapper 没有 member operator() which forwards the argument(s),这与 std::reference_wrapper 不同。因此,它仅对通过引用传递普通参数有用,而不是预期被调用的函数或仿函数。

    示例 3 失败,因为 Boost.Bind relies on a specific protocol to get the result type of the function or functor you pass,如果您使用没有显式返回类型的版本。如果将指针函数或成员函数指针传递给它,则返回的活页夹对象有一个嵌套的result_type 设置为所述PTF 或PTMF 的返回类型。如果你传递了一个函子,它需要一个嵌套的result_type
    std::bind,另一方面,如果你的函子没有,则根本没有嵌套的result_type

    请注意,正如我所说,您可以将结果类型显式提供给 boost::bindstd::bind

    std::for_each(vec.begin(), vec.end(), impl::bind<void>(impl::ref(f3), _1));
    //                                              ^^^^^^
    

    这修复了示例并使其编译。

    【讨论】:

    • 您提供的代码对我有用,我想这是同时支持 boost 和 std 绑定的唯一方法。我将更彻底地阅读 cppreference 和 boost 文档,以更好地理解这些差异。谢谢!
    【解决方案2】:

    std::refboost::ref 相比有一个主要优势:它提供了一个可变的完美转发operator(),它将调用转发到其包含的引用。

    boost::ref 实际上无法做到这一点,因为它需要大量的重载。然而,为了实现这一点,boost::bind(和其他一些类)都为boost::reference_wrapper 提供了特殊处理。

    【讨论】:

      猜你喜欢
      • 2020-10-02
      • 1970-01-01
      • 2018-10-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-05
      • 2012-12-28
      相关资源
      最近更新 更多