C ++概念复合要求和返回类型要求

时间:2020-04-24 14:34:44

标签: c++ c++20

我上一次在GCC中使用C ++概念,并且fconcepts标记了下面的代码片段

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

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

因此,完美的可读性和(对于C ++标准)简短的代码段成为了

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概念中的“隐式使用的模板参数”非常令人讨厌和混乱。

1 个答案:

答案 0 :(得分:8)

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

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

这是否意味着a == b必须具有确切的类型 bool,还是意味着如果您衰减了类型,则会得到bool(即{{1} }或const bool可以),还是意味着可以转换为bool&(即bool可以)?我认为从语法上看这还不是很清楚-特定概念可能会有意义地期望这三个中的任何一个(正如P1452当时指出的std::true_typeSame<T>的概念是40-14)。

该论文还继续指出,在存在ConvertibleTo<T>的Concepts TS中,我们还能够将-> Type ...或vector<Concept>这样的东西写为需求。这是一种类型,但是使用我们在P1084中采用的-> vector<Concept>语义很难表现。

基本上,我认为“完全可读”的代码段实际上不是-该语法有多种潜在含义,根据上下文,所有这些含义都可能是所需的含义。当时最常用的一个(decltype(())甚至都不是我们想要的一个(same_as<bool>)。


我个人认为,convertible_to概念中的“隐式使用的模板参数”非常烦人和令人困惑。

它在C ++中是新颖的,但我个人发现在这些情况下,它的读法非常好。看到:

convertible_to<bool>

只需按照要求进行读取:{ a == b } -> convertible_to<bool>; 必须是可转换为a == b的有效表达式。对于一元概念,由于您可以使用它们代替有些无意义的bool / typename关键字,因此它的用法非常好:

class

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

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

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

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

因此,即使使用更长格式的语法,您也将编写pub trait Iterator { ... } ,而在C ++中,您仍将编写where I: Iterator

这与原始问题并不严格相关,但是我发现添加其他颜色很有趣。