is_invocable_r 忽略返回参数

lig*_*ulb 5 c++ templates c++17

std::conjunction在对我有关不短路(连接模板不短路)的问题的评论中,有人建议我std::is_invocable_r作为解决我的问题的方法。然而,当我尝试使用它时,我发现了一些非常奇怪的行为。例如,此代码使两个断言均失败:

#include <type_traits>

int main()
{
    static_assert(!std::is_invocable_r_v<void, int(int), int>);
    static_assert(std::is_convertible_v<int,void>);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

is_invocable_r请注意cppreference描述:

确定是否Fn可以使用参数调用ArgTypes...以产生可转换为 的结果R

显然int不可转换为void,第二个断言证实了这一点。问题是为什么会std::is_invocable_r_v<void, int(int), int>产生一个true值。这是一个实例: https: //godbolt.org/z/HywH7D

请注意,可以std::is_void_v<std::invoke_result_t<int(int),int>>在此处获取正确答案(https://godbolt.org/z/YMvc47),但这不是我的问题。(它并不能解决我的连词问题)。

Hol*_*Cat 3

就在之后

确定是否Fn可以使用参数调用ArgTypes...以产生可转换为 的结果R。...

它给出了更严格的定义:

... 形式上,确定INVOKE<R>(declval<Fn>(), declval<ArgTypes>()...)当被视为未计算的操作数时是否格式良好,CallableINVOKE中定义的操作在哪里

Callable中,它解释了这INVOKE<void>是一种特殊情况。它不是将返回值隐式转换为R,而是使用static_cast<void>(...)(对于任何返回类型都是格式良好的)。