2009-09-23 48 views
3

我有一個簡單的類是這樣的:使用std :: bind2nd與引用

class A 
{ 
public: 
    void f(const int& n) 
    { 
     std::cout<<"A::f()" << n <<"\n"; 
    } 
}; 

,我試圖用這樣的:

std::vector<A> vec; 
A a; 
vec.push_back(a); 
std::for_each(vec.begin(), vec.end(), std::bind2nd(std::mem_fun_ref(&A::f), 9)); 

但是,當我編譯代碼我得到以下錯誤內部的功能的頭文件某處:

錯誤C2529:「_right」:參照 參考是非法

如果我刪除參數f()中的引用,它編譯得很好。我該如何解決這個問題?我不想刪除引用,因爲在我的真實代碼中複製對象的代價非常高。另外,我沒有使用提升。

+0

您是否檢查了此鏈接? http://www.velocityreviews.com/forums/t290345-stdmemfunref-and-bind2nd-question。html – vpram86 2009-09-23 08:11:19

回答

5

你不能這麼做,很抱歉。只要考慮它不包括在std::bind1ststd::bind2nd(有點像3個參數的函數等)的情況之一。 Boost會有所幫助 - boost::bind支持透明地參考,也有boost::ref

如果您的實現支持TR1 - 最新的g ++版本和VC++ 2008 SP1都可以 - 那麼您可以使用std::tr1::bind,它大部分與boost::bind相同,但是標準化。

+0

「標準化」有點誇張,我想。技術報告至多是一個準標準。不幸的是,它並沒有說明如何包含頭文件。 G ++採用風格,而在VC++中 - 糾正我,如果我錯了 - 標題包含沒有領先的「tr1 /」。 – sellibitze 2009-09-23 22:04:55

+0

那麼,它仍然是一個由委員會設計的文件,可以被實現者重用。關於標題名稱--TR規範始終將它們稱爲「」,因此沒有歧義;如果g ++ _requires_' ',那麼它不符合 - 但你確定這是一個要求,而不是一個選項?在任何情況下,'std :: tr1 :: bind'都被指定爲不在新的單獨頭文件中,而是作爲現有頭文件''的補充。 – 2009-09-23 23:25:11

+0

我不同意你的解釋,GNU顯然也沒有。見1.3/3-4。讓我引用第4段:「建議標準頭文件中的附加聲明使用未默認定義的宏進行保護,否則,所有擴展頭文件(包括具有非標準聲明的標準頭文件的新頭文件和並行版本)放置在不屬於默認搜索路徑_的部分的_separate目錄中 – sellibitze 2009-10-03 08:23:06

2

我不相信你可以將參數綁定到需要引用的方法。 (不在STL中,我認爲升級版可能會讓你這樣做,但我不確定)

你需要自己推出。

struct CallF 
{ 
    CallF(int const& data): m_data(data) {} 
    void operator()(A& val) const 
    { 
     val.f(m_data); 
    } 
    int const& m_data; 
}; 

使用這樣的:

std::for_each(vec.begin(), vec.end(), CallF(9)); 
0

實際上,編譯器錯誤消息道出了原委:

錯誤C2529: '_right':引用來引用是非法

std :: binder將參數作爲引用 - 你不能傳遞一個引用ar eference。

沒辦法。

1

我被同樣的問題困住了。如果你看看C++標準,你會發現它實際上是一個「庫缺陷」。符合C++的實現根本無法處理參考參數。 mem_fun_ref返回具有嵌套typedef的類的對象(

argument_type, first_argument_type, second_argument_type 

)其中引用未被除去。 bind1st和bind2nd被指定爲有一個運算符(),它將引用作爲參數。如果argument_type已經是引用,那麼將無法編譯。

一個解決方案可能是將memfunref替換爲您自己的模板魔法,並刪除嵌套的argument_type typedefs的引用。