Em C++20, subsunção de conceito se refere a um conceito sendo um superconjunto de outro conceito. Por exemplo, no exemplo a seguir, Fooable
subsumes 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);
};
O compilador é capaz de ver que BetterFooable
é definido como Fooable
e outra coisa e, portanto, qualquer tipo que satisfaça BetterFooable
também deve necessariamente satisfazer Fooable
.
Isso nos permite especializar parcialmente as classes de modelo:
template <Fooable T1>
struct MyStruct1 {};
template <BetterFooable T1>
struct MyStruct1<T1> {};
Entretanto, uma especialização de uma classe com um pacote de parâmetros de modelo parece não ser aceitável nem no GCC nem no Clang, mas aceitável no MSVC ( link godbolt ):
template <Fooable... Ts>
struct MyStruct2 {};
template <BetterFooable... Ts>
struct MyStruct2<Ts...> {};
O erro produzido pelo GCC está abaixo, e o erro produzido pelo Clang é muito semelhante:
<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 {};
| ^~~~~~~~~
O GCC e o Clang estão corretos em rejeitar esse código? E há alguma maneira alternativa de expressar a subsunção de conceitos em pacotes de parâmetros de modelo?