看这段代码(godbolt):
template <typename TYPE>
constexpr bool c1 = TYPE::c1;
template <typename TYPE>
constexpr bool c2 = TYPE::c2;
template <typename TYPE>
requires c1<TYPE>
struct Foo {};
template <typename TYPE>
requires c1<TYPE> && c2<TYPE>
struct Foo<TYPE> {};
此代码可以使用 MSVC 进行编译,但不能使用 gcc/clang 进行编译(注意:如果将
constexpr bool
更改为 concept
,则代码可以编译)。
示例中的部分特化是否比主模板具有更特化的约束?我试图弄清楚
c1<TYPE>
和 c2<TYPE>
是否是原子约束。
基于 temp.constr.normal,我预计
E1 && E2
的形式总是分为两部分,因此 c1<TYPE>
应该是原子的,并且代码应该编译。甚至,temp.constr.atomic/1有一个注释“原子约束是通过约束规范化形成的。E从来不是逻辑与表达式,也不是逻辑或表达式”。由于 c1<TYPE> && c2<TYPE>
是逻辑和表达式,因此基于此注释它不应该是原子的。
但另一方面,temp.constr.normal 对于
concept
s 有明确的规则。这个规则对于创建 concept
原子不是必要的,因为如果 E1 && E2
总是分成两部分,无论如何它们都会变成原子的。
哪个编译器是正确的?如果是gcc/clang,我的误解在哪里?
两个原子约束,
和e1
,如果它们是由相同表达式的相同外观形成的,则它们是相同e2
两种声明的外观不同。即,第一个声明中的
c1<TYPE>
与第二个声明中的 c1<TYPE>
不同。
因此,两者都不能包含另一个,因此第二个模板声明并不比第一个模板声明更专业。