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

12
C++20新增了概念,并且标准库中包含了相当多的概念。其中一个概念引起了我的注意:std::invocable,它验证了一个函数对象是否能够使用一组参数进行调用。 std::invocable只是std::is_invocable的语法糖。然而,标准库进一步定义了std::is_invocable_r,它测试一个函数对象是否能够使用一组参数进行调用,并且在调用后返回特定的类型。这两个工具还有nothrow版本。然而,在标准中并没有定义相应的概念。
标准为什么没有定义这些概念?是因为疏忽了还是有什么细微之处被一般读者忽略了,导致委员会决定不包含这些概念呢?

3
std::is_invocable_r并不测试一个函数对象是否返回特定类型R。它测试的是返回类型是否可以转换为R。我怀疑这里的理由与在概念的最终设计中有std::same_asstd::convertible_to的原因相同。也就是说,两者都是有效的,所以标准不会随意选择一个,让我们在需要时自行选择。 - undefined
1个回答

13
概念库的设计方法比类型特征更加简约。例如,没有std::arithmetic概念来匹配std::is_arithmetic特征。这有两个原因:
1. 它可以从std::is_arithmeticstd::integralstd::floating_point简单构建。 2. 不清楚应该优先选择哪种构建方式。
另请参阅:{{link1:在C++标准库中是否会有一个算术类型的概念?}} 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_r来构建它,但不清楚是否仍然应该使用std::convertible_to
总之,概念库中不包括以下问题的概念:
  1. 这个概念可以很容易地从其他概念构建出来,所以它只是为了方便而存在。这包括nothrow变体,_r变体,像std::arithmetic这样的析取等。用户可以自己创建这些。

  2. 存在多种可能的实现方式,不完全清楚哪种实现方式应该纳入标准库。请记住,概念的确切定义方式可能使其比另一个概念更受限制,因此实现细节很重要。

请注意,概念的标准化在很大程度上是由ranges库推动的,并且std::invocable_r对于约束ranges并不是必要的。std::invoke在std::indirect_result_t中被std::indirectly_writable使用。
标准化提案的难度
最后但并非最不重要的是,请记住,标准化任何语言特性都是一项困难的任务。提案越简洁,通过委员会的难度就越小。如果现在有人提出了提供这样方便的概念的提案,很有可能会取得成功,然而,在过去的日子里,这将是一项艰巨的任务,这将大大增加提案的规模(P9898:标准库概念)。

3
用户可以自己制作这些。对于一个新的C++程序员来说,能够使用概念作为抽象层,而不必理解底层(并且不太直观)的C++11元编程库,这难道不是令人向往的吗?其他观点也非常有道理。 - undefined
3
@TooTone 是的,当然。即使实现相对简单,拥有额外的便利概念也是有好处的。这就是为什么我说提出便利概念的建议可能会取得成功。只是在过去,将其标准化需要付出太多努力,而回报却太少。 - undefined
2
人们还可以想象一个外部(仅包含头文件)库提供方便的概念;并不是所有的东西都需要成为标准库的一部分。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接