Difference between std::result_of and decltype

后端 未结 2 1455

I have some trouble understanding the need for std::result_of in C++0x. If I understood correctly, result_of is used to obtain the resulting type o

2条回答
  •  生来不讨喜
    2020-11-29 17:57

    If you need the type of something that isn't something like a function call, std::result_of just doesn't apply. decltype() can give you the type of any expression.

    If we restrict ourselves to just the different ways of determining the return type of a function call (between std::result_of_t and decltype(std::declval()(std::declval()...)), then there is a difference.

    std::result_of is defined as:

    If the expression INVOKE (declval(), declval()...) is well formed when treated as an unevaluated operand (Clause 5), the member typedef type shall name the type decltype(INVOKE (declval(), declval()...)); otherwise, there shall be no member type.

    The difference between result_of::type and decltype(std::declval()(std::declval()...) is all about that INVOKE. Using declval/decltype directly, in addition to being quite a bit longer to type, is only valid if F is directly callable (a function object type or a function or a function pointer). result_of additionally supports pointers to members functions and pointers to member data.

    Initially, using declval/decltype guaranteed a SFINAE-friendly expression, whereas std::result_of could give you a hard error instead of a deduction failure. That has been corrected in C++14: std::result_of is now required to be SFINAE-friendly (thanks to this paper).

    So on a conforming C++14 compiler, std::result_of_t is strictly superior. It's clearer, shorter, and correctly supports more Fs.


    Unless, that is, you're using it in a context where you don't want to allow pointers to members, so std::result_of_t would succeed in a case where you might want it to fail.

    With exceptions. While it supports pointers to members, result_of will not work if you try to instantiate an invalid type-id. These would include a function returning a function or taking abstract types by value. Ex.:

    template >
    R call(F& f) { return f(); }
    
    int answer() { return 42; }
    
    call(answer); // nope
    

    The correct usage would've been result_of_t, but that's a detail you don't have to remember with decltype.

提交回复
热议问题