2012-11-06 19 views
18

假設我有一個函數有兩個參數,爲什麼從綁定返回的對象會忽略額外的參數?

void f(int x, int y); 

,我想綁定其中之一。我可以用std::bind如下:

auto partiallyBoundF = std::bind(f, 10, _1); 

partiallyBoundF只有一個參數,但我可以用一個以上的調用它。超越第一的爭論甚至不必是一個類型,使任何意義的:

partiallyBoundF(20, 0); 
partiallyBoundF(0, 44, -99, "Hello", 4.5, true, []{}); 

bind返回允許什麼對象的目的,要傳遞額外的參數?它允許調用錯誤進行編譯,而其他任何地方都會被拒絕。

+3

什麼編譯器?我想這可能只是一個不合規的編譯器(因爲允許那些額外的參數實際上沒有意義,我懷疑標準允許這樣做)。例如,MSVC通過定義每個可變參數模板來模擬可變參數模板,以獲取最大可能的模板參數,並將這些參數默認爲某些NIL類型。也許這樣的事情是你行爲的原因? –

+3

@ChristianRau:這是標準的一部分。它也是TR1的一部分。 20.8.2/4提出了一個意見,即期望的實現是用於一個可變參數模板化的operator(),只需要傳遞給它的任何東西,而不管參數的類型或數量。 TR1有類似的措辭。 – KnowItAllWannabe

+1

在你的情況下,f(w1,...,wN)其中'N = sizeof ...(bound_args)'(綁定調用的參數個數)應該是一個有效的表達式,見20.8.9.1.2/2和20.8.2/1。編輯:它不禁止任何其他方式來調用它。 – dyp

回答

16

忽略額外的參數很容易實現,實際上可能有用。

在典型的實現中,例如, libstdC++(g ++),採取的方法是將operator()參數收集到一個元組中,然後讓std::placeholder綁定參數根據需要提取它們。強制參數計數需要計算使用的佔位符的數量,這將非常複雜。請注意,可調用綁定可以是具有多個或模板化operator()調用模式的函數,因此無法使用單個「正確」簽名生成綁定對象operator()

另外請注意,你可以寫:

std::bind(&foo, std::placeholders::_1, std::placeholders::_3); 

即明確地忽略了第二個參數綁定對象。如果bind強制執行其參數計數,則需要另外一種方法來指定例如第四個論點也被忽略了。

至於有效性,考慮部件的信號處理程序綁定到一個信號:

sig.connect(std::bind(&C::on_sig, this, param, std::placeholders::_1)); 

如果sig有額外的不想要的發射參數,則它們被簡單地通過bind對象忽略;否則,將同一個處理程序綁定到多個信號將需要編寫多個轉發包裝程序,而不是真正的目的。

+3

「更有用」 - 我會辯論這一點。這打破了強大的打字。如果需要,只要使用接受可變參數的代理仿函數,這個行爲仍然可以通過嚴格的'std :: bind'來模擬。 –

+2

@KonradRudolph如果可調用函數是一個帶有多個'operator()'的函數,則在一般情況下,綁定表達式不會*具有明確定義的類型。 – ecatmur

+0

您可以使用lambda忽略第四個參數。雖然不是很好。 – dyp

相關問題