2010-04-22 94 views
82

我在理解C++ 0x中需要std::result_of時遇到了一些麻煩。如果我理解正確,result_of用於獲取調用具有特定類型參數的函數對象的結果類型。例如:std :: result_of和decltype之間的區別

template <typename F, typename Arg> 
typename std::result_of<F(Arg)>::type 
invoke(F f, Arg a) 
{ 
    return f(a); 
} 

我真的沒有看到下面的代碼的區別:

template <typename F, typename Arg> 
auto invoke(F f, Arg a) -> decltype(f(a)) //uses the f parameter 
{ 
    return f(a); 
} 

template <typename F, typename Arg> 
auto invoke(F f, Arg a) -> decltype(F()(a)); //"constructs" an F 
{ 
    return f(a); 
} 

唯一的問題我可以用這兩種解決方案看到的是,我們需要:

  • 有一個實例的函子在傳遞給decltype的表達式中使用它。
  • 知道函數的定義構造函數。

我說得對不對在想,decltyperesult_of之間的唯一區別是,而第二個不第一個需要表達?

回答

78

result_ofintroduced in Boost,然後included in TR1,最後是C++ 0x。因此,result_of具有向後兼容的優點(具有合適的庫)。

decltype在C++ 0x中是一個全新的東西,並不僅限於函數的返回類型,而且是一種語言特性。


無論如何,在GCC 4.5,result_of在條款實施的decltype

template<typename _Signature> 
    class result_of; 

    template<typename _Functor, typename... _ArgTypes> 
    struct result_of<_Functor(_ArgTypes...)> 
    { 
     typedef 
     decltype(std::declval<_Functor>()(std::declval<_ArgTypes>()...)) 
     type; 
    }; 
+0

好的,所以它主要是一個方便的類來避免decltype中的醜陋表達,對嗎? – 2010-04-22 12:09:31

+2

@Luc:是的。 :)(遲到!) – GManNickG 2011-02-24 04:21:16

+2

@GMan:遲到比從未好;)! – 2011-02-24 16:43:07

10

如果你需要的東西是不是像一個函數調用類型,std::result_of少了點應用。 decltype()可以給你任何表達式的類型。

如果我們僅限於確定函數調用的返回類型的不同方式(在std::result_of_t<F(Args...)>decltype(std::declval<F>()(std::declval<Args>()...)之間),則存在差異。

std::result_of<F(Args...)定義爲:

如果表達式 INVOKE (declval<Fn>(), declval<ArgTypes>()...)是很好時作爲 未計算的操作數(第5章),所述 構件的typedef類型應命名 類型decltype(INVOKE (declval<Fn>(), declval<ArgTypes>()...)); 其它處理形成 ,應該沒有成員 類型。

result_of<F(Args..)>::typedecltype(std::declval<F>()(std::declval<Args>()...)之間的差異是所有關於那個INVOKE。直接使用declval/decltype,除了輸入的時間稍長之外,只有在可以直接調用F(函數對象類型或函數或函數指針)時纔有效。result_of還支持指向成員函數的指針和指向成員數據的指針。

最初,使用declval/decltype保證SFINAE友好的表達式,而std::result_of可能會給您一個硬錯誤,而不是扣除失敗。這已在C++ 14中得到糾正:std::result_of現在需要SFINAE友好(感謝this paper)。

因此,對於符合C++ 14編譯器,std::result_of_t<F(Args...)>是嚴格優越的。它更清晰,更短,並且正確&dagger;支持更多F s &Dagger;


&匕首;除非您在不希望允許指向成員的上下文中使用它,否則 std::result_of_t會在您希望它失敗的情況下成功。

&Dagger;有例外。雖然它支持指向成員的指針,但如果嘗試實例化一個無效的type-id,則result_of將不起作用。這些將包括一個函數返回一個函數或按值抽取類型。例:

template <class F, class R = result_of_t<F()>> 
R call(F& f) { return f(); } 

int answer() { return 42; } 

call(answer); // nope 

正確的用法會一直result_of_t<F&()>,但是那是你沒有與decltype記住一個細節。

+0

對於非引用類型'T'和函數'模板 result_of_t 調用(F && f,T && arg){return std :: forward (f)(std: :移動(ARG)); },'result_of_t'的用法是否正確? – 2016-06-20 10:13:12

+0

另外,如果我們傳遞給'f'的參數是'const T',我們應該使用'result_of_t '? – 2016-06-20 10:17:28

相關問題