具有多个模板参数的概念

Lap*_*apo 6 c++ templates c++-concepts c++20

我正在尝试使用 C++20 概念,开始熟悉它们。我对简单的概念感到很舒服,例如使用标准概念movable我可以写这样的东西(在所有示例中,我想我using namespace std和我都包括在内,<concepts>并且需要任何其他标题):

template<movable T>
int foo (T obj);
Run Code Online (Sandbox Code Playgroud)

并确保在调用此函数时obj可以移动传递的对象。我什至可以用更长的形式写这个:

template<typename T>
requires movable<T>
int foo (T obj);
Run Code Online (Sandbox Code Playgroud)

结果是一样的(我认为)。

但是现在让我们看看另一个概念,例如same_as. same_as需要 2 个模板参数(要比较的 2 种类型),所以我可以写:

template<typename T>
requires same_as<T, string>
int bar (T obj);
Run Code Online (Sandbox Code Playgroud)

现在 T 是string。但是我怎样才能写成更短的形式呢?我试过了,我可以写这个(正如我直觉所期望的):

template<same_as<string> T>
int bar (T obj);
Run Code Online (Sandbox Code Playgroud)

但是这种形式背后的正式规则是什么?

函数模板参数的名称( T)是否作为概念模板的第一个参数输入?或者也许是最后一次?我不知道,关于这个主题的信息很少。我的意思是,在这个例子中它是无关紧要的,因为same_as<A, B> 在语义上等同same_as<B, A>,但在某些情况下,顺序很重要。


我知道有类似标题的问题,例如this one,但它提出了不同的问题。

这些是我试图从中获取信息但失败的资源:cppReferencecppModernesopen-std (我浏览了2018、2019和 2020 年)这篇文章

Bar*_*rry 6

但是这种形式背后的正式规则是什么?

[temp.param]/4 中描述了规则(您正确猜到了):

类型约束 Q,它指定待概念C可以被用来约束上下文确定的类型或模板类型参数包T约束表达式 E定义如下。如果Q是 形式C<A1, ?, An>,那么让E?C<T, A1, ?, An>。否则,我们E?C<T>。如果T不是包,则EE?,否则E(E? && ...)。这种约束的表达 E被称为立即申报约束Q进行T。由类型约束指定的概念应为类型概念([temp.concept])。

以下段落中的示例:

一个类型参数与一个启动型约束介绍的,立即宣布的约束类型约束的参数。[ 例子:

template<typename T> concept C1 = true;
template<typename... Ts> concept C2 = true;
template<typename T, typename U> concept C3 = true;

template<C1 T> struct s1;               // associates C1<T>
template<C1... T> struct s2;            // associates (C1<T> && ...)
template<C2... T> struct s3;            // associates (C2<T> && ...)
template<C3<int> T> struct s4;          // associates C3<T, int>
template<C3<int>... T> struct s5;       // associates (C3<T, int> && ...)
Run Code Online (Sandbox Code Playgroud)

— 结束示例 ]

您也可以将其template <C T>视为 的简写template <C<> T>,然后类型参数T始终插入该概念的第一个参数。