为什么std::invoke_result_t为一个可调用特性提供了其他返回类型



代码段:

#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>);
}

演示

为什么std::invoke_result_t会从foo返回类型中剥离const

我想将一个可调用函数包装成另一个具有完全相同返回类型的可调用函数,但显然我不能依赖std::invoke_result_t

因为这就是语言的工作方式。

函数的返回类型名义上可以是const限定的(这就是您从CallableTrait中得到的(,但调用这样一个函数(即包含函数调用的表达式(的实际结果是,如果它是内置类型(因为无用(,则会去掉const,这就是invoke_result告诉您的。

[expr.type/2]:如果一个prvalue最初具有类型">cvT",其中Tcv不合格的非类、非数组类型,则在进行任何进一步分析之前,表达式的类型将调整为T

诚然,这有点奇怪,但事实就是这样。

最新更新