(注:正如應該已經從標籤清楚,這是嚴格C++ 03是的,我知道,拉姆達使得這一切痛苦消失(在新帶來的種類,我打賭),但這是一個嵌入式系統,具有90年代的操作系統版本,我被告知應該很高興我有一個C++ 03編譯器(GCC4.1.x,BTW)或C++因此,請放棄發佈C++ 11解決方案,不需要蹭它,真的。
另外,std::bind()
,std::function()
等當然實際上在std::tr1
,但我編輯了tr1
前綴,因爲我認爲它在代碼中只增加了噪聲。)如何用std :: bind做到這一點?
我有一些類似服務器的東西,我需要註冊的功能,我需要調整它們來調用一些對象的相似但略有不同的功能。這些函數有不同的參數列表。服務器「知道」,當我嘗試註冊一個函數時,它只接受一個帶有正確簽名的函數(正如std::function
要求的那樣),這取決於作爲模板參數傳入的一些魔術標記。
這裏的代碼的草圖:
// this I just use
class server {
public:
template<unsigned int MagicTag>
bool register_call(typename some_traits_type<MagicTag>::func_type);
};
// this needs to be called from the server
class X {
public:
bool foo();
bool bar(std::string&);
bool baz(int);
};
// this is the glue
class Y {
public:
Y(X& x) : x_(x) {
register_call<MAGIC_FOO>(&Y::foo );
register_call<MAGIC_BAZ>(&Y::bar, _1);
register_call<MAGIC_FBZ>(&Y::baz, _1);
}
private:
X& x_;
template<unsigned int MagicTag, typename Function>
bool register_call(Function function) {
somewhere->register_call<MagicTag>(std::bind(function
, this));
}
template<unsigned int MagicTag, typename Function, typename PlaceHolder1>
bool register_call(Function function, PlaceHolder1 place_holder1) {
somewhere->register_call<MagicTag>(std::bind(function
, this
, place_holder1));
}
int foo() {return x_.foo() ? MAGIC_OK : MAGIC_FAILED;}
int bar(std::string& s) {return x_.bar(s) ? MAGIC_OK : MAGIC_FAILED;}
int baz(int i) {return x_.baz(i) ? MAGIC_OK : MAGIC_FAILED;}
};
這實際工作,但在現實中有這樣多的功能,做這個作爲一個乏味的copy'n'paste努力侮辱我的尊嚴感和產生臭味的代碼。由於所有這些函數的功能完全相同,唯一不同的是它們調用的函數以及它們具有或不具有的參數,所以我應該能夠將它們摺疊成一個參數化函數,從而將差異隱藏在std::bind()
之後。如果做不到這一點,我首先對沒有任何參數的所有功能(如foo()
)這樣做,這是絕大多數。
int call_it(std::function<bool()> f) {return f() ? MAGIC_OK : MAGIC_FAILED;}
,並綁定在X
相應的函數作爲參數傳遞給它:
所以我通過一個單一功能Y::call_it
,做繁瑣的部分想航線的foo()
樣功能的所有調用X
:
register_call<MAGIC_FOO>(&X::foo); // note the X!
// (this is wrong)
somewhere->register_call<MagicCode>(std::bind(std::bind(&Y::call_it
, this
, function)
, std::ref(x_));
顯然,這是錯誤的,所以我所有的其他嘗試來解決這個問題。 (我現在只玩了std::bind()
10周,所以請耐心等待)。最後,我迷失在一個令人難以置信的迷宮中,這些迷人的錯誤信息來自於std::function
的模板化膽量,它可以讓一個成年男子流下眼淚,至少應該讓他的家庭縮水一年。
所以在我之前kill myself out of sheer frustration和孤兒我的孩子 - 我怎麼能這樣做?
我從來沒有使用過std :: bind。那是爲了認罪。但是,你不想'register_call(std :: bind(&Y :: call_it,this,std :: bind(ptmf,std :: ref(x_)));'? –
rici
@rici:當然,你是對的。[我已經看到了這個我自己](http://chat.stackoverflow.com/transcript/10?m=6878122#6878122。)它只是我一直在撞我的頭撞牆小時,而這只是1001號中間的混亂狀態,試圖讓它工作,這是當我決定要問這個問題的時候,然而,問題是我不能以另一種方式工作,_sigh._ – sbi
我想這就是爲什麼我從來沒有使用過std :: bind模板metadebugging是瘋狂的,或者它讓你瘋狂,這可能是爲什麼所有標準庫實現都不合標準。祝你好運! – rici