简体   繁体   中英

Why std::invoke_result_t gives other return type for a callable than a trait?

Snippet:

#include <functional>

template <typename T>
struct CallableTrait;

template <typename R, typename... Args>
struct CallableTrait<std::function<R(Args...)>>
{
    using ReturnType = R;
};

template <typename Callable>
using CallableTraitT = CallableTrait<decltype(std::function{std::declval<Callable>()})>;

const int foo(const int x)
{
    int r = x + 42;
    return r;
}

int main()
{
    using ReturnT1 = CallableTraitT<decltype(foo)>::ReturnType;
    using ReturnT2 = std::invoke_result_t<decltype(foo), decltype(42)>;

    static_assert(std::is_same_v<ReturnT1, const int>);
    static_assert(std::is_same_v<ReturnT2, int>);
}

Demo

Why does std::invoke_result_t strip off the const from the foo return type?

I would like to wrap a callable into another callable with the exact same return type, but apparently I cannot rely std::invoke_result_t for this.

Because that's how the language works.

A function's return type can be nominally const -qualified (and that's what you're getting out of CallableTrait ), but the actual result of invoking such a function (ie the expression containing the function call) has the const stripped off if it's a built-in type (for being useless), and that's the thing that invoke_result is telling you about.

[expr.type/2] : If a prvalue initially has the type “ cv T ”, where T is a cv-unqualified non-class, non-array type, the type of the expression is adjusted to T prior to any further analysis.

Admittedly this is a bit of an oddity, but that's how it is.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM