好吧,这实际上意味着什么:
template <typename T, typename U>
concept equality_comparable = requires(T a, U b) {
{ a == b } -> bool;
{ a != b } -> bool;
};
是不是意味着a == b
必须有类型exactly bool
,或者这是否意味着如果你衰减你得到的类型bool
(i.e. const bool
or bool&
都可以),或者这是否意味着可以转换为bool
(i.e. std::true_type
可以吗)?我认为从语法上看,这根本不是很清楚 - 并且这三个中的任何一个都可以由特定概念有意义地期望(如P1452 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1452r2.html指出,当时的比例Same<T>
to ConvertibleTo<T>
概念为 40-14)。
论文还指出,在 Concepts TS 中,-> Type
存在,我们也有能力写类似的东西vector<Concept>
... or -> vector<Concept>
作为要求。这是一种类型,但很难与decltype(())
我们采用的语义P1084 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1084r2.pdf.
基本上,我不认为“完全可读”的片段实际上是 - 该语法有多种潜在含义,所有这些都可以是所需的含义,具体取决于上下文。以及当时最常用的一种(same_as<bool>
)甚至不是我们想要的(convertible_to<bool>
).
就我个人而言,我发现 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)
那里的“隐式使用的模板参数”是如此隐含,以至于它甚至不是特质声明 https://doc.rust-lang.org/src/core/iter/traits/iterator.rs.html#96-3214,它也隐含在那里:
pub trait Iterator { ... }
因此,即使使用较长形式的语法,您也会写where I: Iterator
而在 C++ 中你仍然会写requires range<R>
.
这与原来的问题并不严格相关,但我只是觉得添加其他颜色很有趣。