【问题标题】:is_invocable_r ignoring the return parameteris_invocable_r 忽略返回参数
【发布时间】:2019-07-13 12:25:48
【问题描述】:

在评论我关于 std::conjunction 不是短路 (Conjuction template doesn't short circuit) 的问题时,我被推荐 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;
}

注意cppreferenceis_invocable_r的描述:

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

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

请注意,可以使用std::is_void_v&lt;std::invoke_result_t&lt;int(int),int&gt;&gt; 在这里获得正确答案(https://godbolt.org/z/YMvc47),但这不是我的问题。 (而且它并没有解决我从连词问题中遇到的问题)。

【问题讨论】:

  • 您可能会阅读Callable 以了解INVOKE 的定义,它确实对void 具有特殊行为。

标签: c++ templates c++17


【解决方案1】:

紧接着

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

它给出了更严格的定义:

... 形式上,确定INVOKE&lt;R&gt;(declval&lt;Fn&gt;(), declval&lt;ArgTypes&gt;()...) 在被视为未计算的操作数时是否格式正确,其中INVOKECallable 中定义的操作

Callable 中解释了 INVOKE&lt;void&gt; 是一个特例。它没有将返回值隐式转换为R,而是使用static_cast&lt;void&gt;(...)(对于任何返回类型都是格式正确的)。

【讨论】:

  • 等待static_cast&lt;void&gt;(...) 适用于任何返回类型,但is_convertible&lt;int,void&gt; 为假?这两个人怎么同意?
  • 只需忽略 "确定是否可以使用参数 ArgTypes 调用 Fn... 以产生可转换为 R 的结果。" 部分。正如我所看到的,该页面试图给你一个简单的不精确的解释(“result ... is convertible to R”),然后详细说明这究竟意味着什么(如果R不是void,结果必须隐式转换为R,否则结果可以是任何类型)。
猜你喜欢
  • 2021-01-13
  • 2016-06-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-03
  • 1970-01-01
相关资源
最近更新 更多