2013-08-29 46 views
1

我在我的代碼的各個地方使用std::bind遇到了很多麻煩。有時它有效,有時它不會,所以我認爲我正在做一些根本性錯誤的事情。在gcc中使用std :: bind編譯錯誤4.7

據我瞭解,下面的基本使用std::bind應該很好地工作:

#include <functional> 

int foo(int a, int b){ return a+b; } 

int main(){ 

    using namespace std::placeholders; 

    // works 
    auto bar_auto=std::bind(foo,1,_2); 

    // compile error 
    std::function<int(int)> bar_fun=std::bind(foo,1,_2); 

    int quux=1; 
    // compile error 
    std::function<int(int)> bar_fun_lvalue=std::bind(foo,quux,_2); 

} 

肯定的bar_auto類型爲std::function<int(int)>(1個int參數約束型的foo),所以爲什麼bar_fun失敗編譯?我包含bar_fun_lvalue,因爲一些Google搜索向我顯示rvalues used to be problematic。但是這並沒有解決任何問題。

它類似於this bug,但那已經太舊了,我不認爲它是相關的。

gcc的輸出功率沒有特別啓發:

In file included from bindnew.cpp:1:0: /usr/include/c++/4.7/functional: In instantiation of ‘static _Res std::_Function_handler<_Res(_ArgTypes ...), _Functor>::_M_invoke(const std::_Any_data&, _ArgTypes ...) [with _Res = int; _Functor = std::_Bind))(int, int)>; _ArgTypes = {int}]’: /usr/include/c++/4.7/functional:2298:6: required from ‘std::function<_Res(_ArgTypes ...)>::function(_Functor, typename std::enable_if<(! std::is_integral<_Functor>::value), std::function<_Res(_ArgTypes ...)>::_Useless>::type) [with _Functor = std::_Bind))(int, int)>; _Res = int; _ArgTypes = {int}; typename std::enable_if<(! std::is_integral<_Functor>::value), std::function<_Res(_ArgTypes ...)>::_Useless>::type = std::function::_Useless]’ bindnew.cpp:15:52: required from here /usr/include/c++/4.7/functional:1912:40: error: no match for call to ‘(std::_Bind))(int, int)>) (int)’ /usr/include/c++/4.7/functional:1140:11: note: candidates are: /usr/include/c++/4.7/functional:1211:2: note: template _Result std::_Bind<_Functor(_Bound_args ...)>::operator()(_Args&& ...) [with _Args = {_Args ...}; _Result = _Result; _Functor = int (*)(int, int); _Bound_args = {int, std::_Placeholder<2>}] /usr/include/c++/4.7/functional:1211:2: note:
template argument deduction/substitution failed: /usr/include/c++/4.7/functional:1206:35: error: cannot convert ‘std::_No_tuple_element’ to ‘int’ in argument passing /usr/include/c++/4.7/functional:1225:2: note: template _Result std::_Bind<_Functor(_Bound_args ...)>::operator()(_Args&& ...) const [with _Args = {_Args ...}; _Result = _Result; _Functor = int (*)(int, int); _Bound_args = {int, std::_Placeholder<2>}] /usr/include/c++/4.7/functional:1225:2: note:
template argument deduction/substitution failed: /usr/include/c++/4.7/functional:1219:35: error: cannot convert ‘std::_No_tuple_element’ to ‘int’ in argument passing /usr/include/c++/4.7/functional:1239:2: note: template _Result std::_Bind<_Functor(_Bound_args ...)>::operator()(_Args&& ...) volatile [with _Args = {_Args ...}; _Result = _Result; _Functor = int (*)(int, int); _Bound_args = {int, std::_Placeholder<2>}] /usr/include/c++/4.7/functional:1239:2: note:
template argument deduction/substitution failed: /usr/include/c++/4.7/functional:1233:35: error: cannot convert ‘std::_No_tuple_element’ to ‘int’ in argument passing /usr/include/c++/4.7/functional:1253:2: note: template _Result std::_Bind<_Functor(_Bound_args ...)>::operator()(_Args&& ...) const volatile [with _Args = {_Args ...}; _Result = _Result; _Functor = int (*)(int, int); _Bound_args = {int, std::_Placeholder<2>}] /usr/include/c++/4.7/functional:1253:2: note: template argument deduction/substitution failed: /usr/include/c++/4.7/functional:1247:35: error: cannot convert ‘std::_No_tuple_element’ to ‘int’ in argument passing

回答

5

佔位符位置的物體(例如,當您使用_2)不是的位置您調用的函數中的參數,而是創建的可調用對象中參數的佔位符。相反總是從_1開始並增加。

所以:

auto bar_auto=std::bind(foo,1,_1); 


這意味着你可以通過簡單地做這樣

auto bar_auto=std::bind(foo,_2,_1); 

當「呼叫切換參數由std::bind創建的對象「bar_auto對象,第一個參數將是的第二個參數,調用中的第二個參數將成爲foo的第一個參數。

+0

謝謝,這清除了事情。這會對'bar_auto'的編譯器警告有幫助。有沒有什麼理由讓我的這種愚蠢的錯誤不會觸發警告? –

+0

@MarcClaesen好吧,它有一種長時間和無法讀取的錯誤。 :) –

+1

雖然這個轉儲不是關於'bar_auto'的。我猜沒有警告,因爲'std :: bind'的結果函數可能有任意數量的參數,所以無法評估給定的佔位符是否不合適(在我的例子中是'_2')。 –

4

_2佔位符是指使用返回算符的第二個參數。因此的

std::bind(foo,1,_2) 

類型不std::function<int(int)>

std::function<int(unspecified_type, int)> 

要獲得std::function<int(int)>,使用

std::bind(foo, 1, _1) 
//    ^^