为什么C++没有 std::invocable_r 概念?

Why does C++ have no std::invocable_r concept?

提问人:Afiefh 提问时间:9/25/2023 最后编辑:Jan SchultkeAfiefh 更新时间:10/4/2023 访问量:1341

问:

C++ 添加了概念,标准库包含了相当多的概念。一个概念特别引起了我的注意:std::invocable,它验证了可以使用一组参数调用函子。

std::invocable只是句法糖。但是,标准库进一步定义了哪些测试是否可以使用一组参数调用函子,以及它是否在调用后返回特定类型。这两个实用程序也有版本。但是,标准中没有定义等效的概念。std::is_invocablestd::is_invocable_rnothrow

标准没有定义这些概念是有原因的,还是只是一个疏忽?是否有一些细枝末节是普通读者没有注意到的,使委员会决定不包括这些?

C ++20 语言设计 C++ 概念

评论

3赞 StoryTeller - Unslander Monica 9/25/2023
std::is_invocable_r不测试函子是否返回特定类型 R。它测试返回类型是否可转换为 R。我怀疑这里的基本原理与概念的最终设计相同。也就是说,两者都是有效的,所以标准不会随意选择一个,让我们在需要时选择。std::same_asstd::convertible_to

答:

13赞 Jan Schultke 9/25/2023 #1

概念库的设计方法比类型特征的设计方法要简约得多。例如,没有与特征相匹配的概念。这有两个原因:std::arithmeticstd::is_arithmetic

  1. 它可以由 , 或从 和 简单构造。std::is_arithmeticstd::integralstd::floating_point
  2. 目前尚不清楚这些结构中的哪一种应该更受欢迎。

另请参阅:C++ 标准库中会有算术类型的概念吗?

一般的便利概念问题和便利性概念std::invocable

和 its 和 variants 也存在类似的问题。你可以简单地构建一个这样的概念:std::invocable_rnothrow

template <typename T, typename R, typename... Args>
concept invocable_r = invocable<T, Args...> && requires (Args&&... args) {
    { invoke(forward<Args>(args...)) } -> convertible_to<R>;
};

但是,目前尚不清楚这是否是最终的实现。你也可以用 来构造它,目前还不清楚是否应该使用。std::invoke_rstd::convertible_to

总之,概念库不包含存在以下问题的概念:

  1. 这个概念可以很容易地从其他概念中构建出来,所以它只是为了方便而存在。这包括变体、变体、分离等。用户可以自己制作这些。nothrow_rstd::arithmetic

  2. 有多种可能的实现,目前还不清楚哪一个应该进入标准库。请记住,定义概念的确切方式可能会使其比另一个概念更受约束,因此实现细节很重要。

请注意,概念标准化主要由范围库驱动,对于约束范围并不是必不可少的。 由 std::indirectly_writable 中的 std::indirect_result_t 使用。std::invocable_rstd::invoke

标准化提案的难度

最后但并非最不重要的一点是,请记住,标准化任何语言功能都是一项艰巨的任务。提案越精简,就越容易通过委员会。如果现在有人提出了一个提供这种便利概念的提案,那么它很有可能获得成功,但是,这在当时将是一项艰巨的任务,这将大大增加提案(P9898:标准库概念)的规模。

评论

3赞 TooTone 9/25/2023
“用户可以自己制作这些。”让一个新的 C++ 程序员能够使用概念作为抽象层,而不必理解底层(和不太直观的)C++11 元编程库,难道不是可取的吗?其他几点很有道理。
3赞 Jan Schultke 9/25/2023
@TooTone是的,当然。即使实现相对简单,拥有额外的便利概念也有好处。这就是为什么我说便利概念的提案可能会获得成功。只是付出了太多的努力,回报太少,以至于无法在当时对其进行标准化。
2赞 Toby Speight 9/26/2023
人们还可以想象一个外部(仅标头)库提供便利概念;并非所有内容都需要成为标准库的一部分。