用std :: tr1 :: bind替换boost :: bind的问题

时间:2011-07-11 16:25:20

标签: c++ boost tr1 boost-bind

我有以下代码,可以在Visual Studio 2008 SP1下编译并运行。

#include <functional>
#include <iostream>

#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/utility.hpp>

class NoncopyableObject : public boost::noncopyable
{
public:
    NoncopyableObject(int x) : x_(x) {}
    int getValue() const {return x_;}
private:
    int x_;
};

template<class F>
class MenuItemDispatcher
{
public:
    MenuItemDispatcher(F f) : f_(f) { }

    void operator ()(NoncopyableObject& w) const
    {
        // Invoke the functor
        f_(w);
    }
private:
    typedef boost::function1<void,NoncopyableObject&> FUNC;
    FUNC f_;
};

void MenuItem()
{
    std::cout << "in MenuItem()\n";
}

template<class F>
MenuItemDispatcher<F> MakeMenuItemDispatcher(F f)
{
    return MenuItemDispatcher<F>(f);
}

int main()
{
    NoncopyableObject obj(7);
    MakeMenuItemDispatcher(boost::bind(&MenuItem))(obj);
}

如果我在main()中将boost :: bind更改为std :: tr1 :: bind,我会收到错误:

  

错误C2248:'boost::noncopyable_::noncopyable::noncopyable':无法访问类'boost::noncopyable_::noncopyable'中声明的私有成员。

     

此诊断发生在编译器生成的函数'NoncopyableObject::NoncopyableObject(const NoncopyableObject &)'

所以它试图为NoncopyableObject生成一个拷贝构造函数。有人知道为什么会这样吗? MenuItemDispatcher的调用操作符接受对NoncopyableObject的引用,所以我很难看出出了什么问题。

1 个答案:

答案 0 :(得分:4)

这似乎与MS Visual Studio(包括2010)和GNU gcc(我测试的4.4.1和4.5.2,两者都按照您预期的方式工作)中实现bind的方式不同/ p>

根据您的定义

,请考虑以下代码
auto b = boost::bind(&MenuItem);
NoncopyableObject obj(7);
b(obj);  // OK in VS and GCC

用std :: bind替换boost :: bind(我使用的是2010,错误信息与你的2008年相同)

auto b = std::bind(&MenuItem);
NoncopyableObject obj(7);
b(obj);  // compile error in VS 2010 SP1, OK in GCC
b(std::reference_wrapper<NoncopyableObject>(obj)); // OK in both

所以,即使不使用该参数,MS的bind()也会复制其参数,而boost和GCC的bind()根本不会对该参数感到烦恼。

通过将FUNC typedef更改为

,我能够让您的示例编译并运行(在2010年)
typedef boost::function1<void, std::tr1::reference_wrapper<NoncopyableObject> > FUNC;