2

我有以下代码在 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,所以我很难找出问题所在。

4

1 回答 1

4

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

考虑以下代码,给定您的定义

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

bind()因此,即使不使用该参数,MS也会复制其参数,而 boost 和 GCCbind()则根本不理会该参数。

通过将FUNCtypedef 更改为

typedef boost::function1<void, std::tr1::reference_wrapper<NoncopyableObject> > FUNC;
于 2011-07-11T19:06:55.713 回答