2014-09-24 34 views
2

以下代碼中的函數invoke是調用另一個函數/函數/ lambda的簡單包裝,因此invoke(f,args...)等於f(args...)。 (這背後的原因是也有成員函數過載,從而允許這兩種用法的一般化的語法。)從仿函數模板參數中推導可變參數和返回類型(特定於MSVC)

此實現工作在克++:

template <class Fn, class ...Args> 
auto invoke(Fn f, Args ...args) -> decltype(f(args...)) { 
    return f(args...); 
} 

int y = invoke([](int x){ return x+1; }, 42); // y = 43 

Demo

然而,MSVC 2012(十一月CTP)抱怨:

Error: C2893: Failed to specialize function template 'unknown-type invoke(Fn,Args...)' 
With the following template arguments: 
'main::<lambda_687537b292ffb7afcfd8f8fc292d6e73>' 
'int' 

(請注意,在錯誤信息的int來自42被傳遞給invoke,而不是來自lambda的論點。我通過傳遞與invoke不同的東西來檢查此問題。)

我該如何解決這個問題以便與MSVC 2012(Nov CTP)一起使用?

的資料我嘗試:

  • 當我改變可變參數模板參數的單個參數(但仍然是一個模板參數,即除去在上面的代碼中的所有...),代碼編譯。但我需要支持任何數量的參數。

  • 它還編譯,如果我用非通用的int返回類型替換尾隨返回類型。但顯然我想支持泛型返回類型。

  • 如果我傳遞函數指針而不是lambda表達式,行爲不會改變。所以它與lambda無關。例如錯誤消息:

    Error: C2893: Failed to specialize function template 'unknown-type invoke(Fn,Args...)' 
    With the following template arguments: 
    'int (__cdecl *)(int)' 
    'double' 
    
+0

在Visual Studio 2013中實現了可變參數模板。請參閱[Support for C++ 11 Features](http://msdn.microsoft.com/zh-cn/library/hh567368.aspx) – 2014-09-24 00:49:04

+0

「'invoke(f, args ...)'等於'f(args ...)'「。對於當前定義的'invoke','invoke(f,std :: move(x))'不等於'f(std :: move(x))'。您需要通過使用通用/轉發引用和「std :: forward」來轉發參數。 – 2014-09-24 00:51:41

+0

@JonathanPotter他們已被添加到MSVC 2012年11月CTP補丁 – leemes 2014-09-24 00:51:43

回答

2

嘗試使用typename result_of<F(Args...)>::type。 (我的意思是這種情況:使用類型而不是數值)。

這不支持標準下的SFINAE,但是如果可能在一半兼容的C++ 11編譯器中工作。

如果你的編譯器沒有爆炸,也可以使用Args&&...和perfect。

+0

不錯!正是我在找什麼。似乎工作(現在)。 – leemes 2014-09-24 01:04:45

相關問題