【问题标题】:C++ concepts compound requirements and return-type-requirementsC++ 概念复合要求和返回类型要求
【发布时间】:2020-04-24 14:34:44
【问题描述】:

上一次我在 GCC 中使用 C++ 概念,并且 fconcepts 标记了以下 sn-p 用于工作

template <typename T, typename U>
concept equality_comparable = requires(T a, U b) {
  { a == b } -> bool;
  { a != b } -> bool;
};

显然情况不再如此,复合要求之后的return-type-requirement现在只能包含类型约束。如果我没记错的话,这基本上意味着使用另一个概念来满足 return-type-requirement

因此,完美可读且(对于 C++ 标准)简短的 sn-p 变为

template <typename From, typename To>
concept convertible_to = std::is_convertible_v<From, To>;

template <typename T, typename U>
concept equality_comparable = requires(T a, U b) {
  { a == b } -> convertible_to<bool>;
  { a != b } -> convertible_to<bool>;
};

当然,这甚至不是一个完整的实现,但我们暂时忽略它。有人可以向我解释为什么委员会决定改变这一点吗?就我个人而言,我发现 convertible_to 概念中的“隐式使用的模板参数”非常令人恼火和令人困惑。

【问题讨论】:

  • "因此完美可读且(对于 C++ 标准)简短的 sn-p 变为" “完全可读”这个短语完全取决于谁在阅读。如果阅读的人不知道-&gt; type 的意思是“可转换为”而不是“相同”,那就有问题了。
  • @Barry 是的,你是对的。我需要一本涵盖概念的 C++ 书籍。

标签: c++ c++20


【解决方案1】:

嗯,这实际上是什么意思:

template <typename T, typename U>
concept equality_comparable = requires(T a, U b) {
  { a == b } -> bool;
  { a != b } -> bool;
};

这是否意味着a == b 必须具有类型完全 bool,还是意味着如果你衰减你得到bool 的类型(即const boolbool&amp; 都可以) ,或者这是否意味着可转换为bool(即std::true_type 可以)?我认为从语法上看一点都不清楚——这三个中的任何一个都可能是一个特定概念有意义的需要(正如P1452 指出的那样,当时Same&lt;T&gt;ConvertibleTo&lt;T&gt; 的比率在概念是 40-14)。

该论文还继续指出,在存在 -&gt; Type 的概念 TS 中,我们还可以编写类似 vector&lt;Concept&gt;... 或 -&gt; vector&lt;Concept&gt; 的内容作为要求。那是一种类型,但是对于我们在P1084 中采用的decltype(()) 语义,它的行为会非常困难。

基本上,我不认为“完全可读”的 sn-p 实际上是 - 该语法有多种潜在含义,所有这些都可能是所需的含义,具体取决于上下文。而当时最常用的(same_as&lt;bool&gt;)甚至不是我们想要的(convertible_to&lt;bool&gt;)。


我个人觉得 convertible_to 概念中的“隐式使用的模板参数”非常令人恼火和混乱。

它在 C++ 中很新颖,但我个人觉得在这些情况下它读起来相当不错。看到:

{ a == b } -> convertible_to<bool>;

完全按照要求读取:a == b 必须是可转换为 bool 的有效表达式。对于一元概念,它的用法非常好,因为您可以使用它们来代替有些无意义的 typename/class 关键字:

template <range R>
void algo(R&& r);

这与其他语言没有什么不同。比如,在 Rust 中:

fn algo<I: Iterator>(i: I)

那里的“隐式使用的模板参数”是如此隐含,以至于它甚至不是trait declaration 的一部分,它也是隐含的:

pub trait Iterator { ... }

因此,即使使用较长形式的语法,您也可以编写 where I: Iterator,而在 C++ 中,您仍然可以编写 requires range&lt;R&gt;

这与原始问题并不严格相关,但我只是觉得添加一些其他颜色很有趣。

【讨论】:

  • 感谢您的澄清。我想我没有以这种方式考虑过一元概念的用法。它确实读得很流利。猜猜我们将不得不等待概念库头文件被实现,因为没有它,概念的使用感觉很受限制。
  • @Vinci gcc 10 将在接下来的几周内发布,并且已经有很多的 C++20。有很多可以玩的!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-01-09
  • 2020-07-24
  • 1970-01-01
  • 2020-12-27
  • 2021-12-20
  • 2020-11-18
  • 1970-01-01
相关资源
最近更新 更多