在 C++20 中,概念包含是指一个概念是另一个概念的超集。例如,在以下示例中,Fooable
包含BetterFooable
:
template <typename T>
concept Fooable = requires(T& t) {
t.foo();
};
template <typename T>
concept BetterFooable = Fooable<T> && requires(T& t, int x) {
t.foo(x);
};
编译器能够看到BetterFooable
定义为Fooable
和其他东西,因此,任何满足的类型BetterFooable
也必须满足Fooable
。
这使得我们可以部分专门化模板类:
template <Fooable T1>
struct MyStruct1 {};
template <BetterFooable T1>
struct MyStruct1<T1> {};
但是,具有模板参数包的类的特化似乎在 GCC 和 Clang 中都是不可接受的,但在 MSVC 中是可以接受的(godbolt 链接):
template <Fooable... Ts>
struct MyStruct2 {};
template <BetterFooable... Ts>
struct MyStruct2<Ts...> {};
GCC 产生的错误如下,Clang 产生的错误非常相似:
<source>:15:8: error: partial specialization 'struct MyStruct2<Ts ...>' does not specialize any template arguments and is not more constrained than the primary template; to define the primary template, remove the template argument list
15 | struct MyStruct2<Ts...> {};
| ^~~~~~~~~~~~~~~~
<source>:12:8: note: primary template here
12 | struct MyStruct2 {};
| ^~~~~~~~~
GCC 和 Clang 是否正确地拒绝了该代码,并且还有其他方法可以在模板参数包中表达概念包含吗?
目前来说,是的。
目前没有。
但是,P2963已被 C++26 接受,其动机正是此处的示例。它至少已在 Clang 19 中实现。