我正在尝试使用C ++ 20概念来开始熟悉它们。
我对简单的概念感到很满意,例如使用标准概念movable
,我可以编写这样的内容(在所有示例中,我都以为using namespace std
,并且包括了<concepts>
和其他任何内容标头):
template<movable T>
int foo (T obj);
并确保在调用此函数时可以移动传递的对象obj
。
我什至可以用更长的形式写出来:
template<typename T>
requires movable<T>
int foo (T obj);
结果将是相同的(我认为)。
但是现在让我们看一下诸如same_as
之类的另一个概念。 same_as
采用2个模板参数(要比较的2种类型),因此我可以这样写:
template<typename T>
requires same_as<T, string>
int bar (T obj);
现在T是string
。但是,我该如何用较短的形式写呢?我尝试过,并且可以编写此代码(正如我的直觉预期):
template<same_as<string> T>
int bar (T obj);
但是此表格的正式规则是什么?
功能模板参数的名称(T
)是作为概念模板的第一个参数输入的吗?还是最后一次?我不知道,关于此主题的信息很少。我的意思是,在此示例中,这是无关紧要的,因为same_as<A, B>
is semantically equivalent到same_as<B, A>
,但是在某些情况下可以肯定顺序很重要。
我知道有些标题相似的问题,例如this one,但问题却有所不同。
这些是我试图从中获取信息的资源,但失败了:cppReference,cppModernes,open-std (I browsed years 2018, 2019 and 2020)和this post。 >
答案 0 :(得分:5)
但是此表格背后的正式规则是什么?
[temp.param]/4中描述了规则(您正确猜中了该规则):
指定概念
Q
的 type-constraintC
可用于将上下文确定的类型或模板类型参数包T
约束为 constraint-expressionE
定义如下。 如果Q
的格式为C<A1, ⋯, An>
,则让E′
为C<T, A1, ⋯, An>
。 否则,将E′
设为C<T>
。 如果T
不是包,则E
是E′
,否则E
是(E′ && ...)
。 此 constraint-expressionE
称为Q
的立即声明约束,用于T
。 type-constraint 指定的概念应为类型概念([temp.concept])。
后段带有示例:
以 type-constraint 开头的 type-parameter 为参数引入了 type-constraint 的立即声明的约束。 [示例:
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> && ...)
-结束示例 ]
您还可以认为template <C T>
是template <C<> T>
的简写,然后类型参数T
总是插入到该概念的第一个参数中。