2011-07-11 148 views
2

問題我有下面的代碼編譯並在Visual Studio 2008 SP1下正常運行。替換boost :: bind與std :: tr1 :: bind

#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 ::綁定到std :: TR1 ::在main()綁定,我得到一個錯誤:

error C2248: 'boost::noncopyable_::noncopyable::noncopyable' : cannot access private member declared in class 'boost::noncopyable_::noncopyable' .

This diagnostic occurred in the compiler generated function 'NoncopyableObject::NoncopyableObject(const NoncopyableObject &)'

所以它試圖產生NoncopyableObject拷貝構造函數。任何人都知道爲什麼這可能是這麼好嗎? MenuItemDispatcher的調用操作符需要一個對NoncopyableObject的引用,所以我很努力地看到出了什麼問題。

+0

,讓您的例子編譯和(2010年)的運行做,如果你打破最後一行分成兩行,你得到同樣的錯誤?我在想一行聲明'MakeMenuItemDispatcher'和一個調用它。只是試圖排除一些奇怪的解析問題與現在的代碼。 –

+0

在gcc 4.4.1,4.5.2中工作,在VS 2010 SP1中失敗。重現一下,試圖創建一個boost/std函數就足夠了,這個函數從boost/std綁定中獲取'Noncopyable&',這並不是 – Cubbi

回答

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 

性病更換的boost ::綁定::綁定(我使用的是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

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

非常感謝你。使用reference_wrapper可以做到這一點。我認爲你的答案有一個小小的錯誤:代碼行(std :: reference_wrapper (obj)); //確定兩者都應該使用std :: ref(或std :: tr1 :: ref)而不是我認爲? – PeteUK

+0

@PUK你說得對,在進行函數調用時使用'ref()'輔助函數更容易閱讀。這與使用make_pair(arg1,arg2)而不是pair (arg1,arg2)相同。 – Cubbi

+0

我多傻。當然 - 這是通過一個函數來進行模板參數推導。謝謝! – PeteUK