Проблема с заменой boost :: bind на std :: tr1 :: bind - PullRequest
2 голосов
/ 11 июля 2011

У меня есть следующий код, который прекрасно компилируется и работает под 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);
}

Если я изменю boost :: bind на std :: tr1 :: bind в main (), яполучить ошибку:

ошибка C2248: 'boost::noncopyable_::noncopyable::noncopyable': невозможно получить доступ к закрытому члену, объявленному в классе 'boost::noncopyable_::noncopyable'.

Эта диагностика произошла в сгенерированной компилятором функции 'NoncopyableObject::NoncopyableObject(const NoncopyableObject &)'

Итак, он пытается сгенерировать конструктор копирования для NoncopyableObject.Кто-нибудь знает, почему это так, пожалуйста?Оператор вызова MenuItemDispatcher берет ссылку на NoncopyableObject, поэтому я изо всех сил пытаюсь понять, что происходит не так.

1 Ответ

4 голосов
/ 11 июля 2011

Похоже, это разница в том, как 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

замена boost :: bind на std :: 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() вообще не беспокоятся об этом аргументе.

Мне удалось получить ваш пример для компиляции и запуска (в 2010 году), изменив FUNC typedef на

typedef boost::function1<void, std::tr1::reference_wrapper<NoncopyableObject> > FUNC;
...