Consider the following example:
template< class A, int B, class C>
struct Obj {
A a_obj;
static constexpr int b_value = B;
C c_obj;
};
template< template<class... > class ... Templates >
struct Foo;
template<>
struct Foo<Obj> {
Obj<void*, 5, float> obj;
};
int main() {
Foo<Obj> foo;
};
This is failing on me (g++ 7.2, with -std=c++17
with the following errors:
templ.cpp:16:15: error: type/value mismatch at argument 1 in template parameter list for ‘template<template<class ...> class ... Templates> struct Foo’
16 | struct Foo<Obj> {
| ^
templ.cpp:16:15: note: expected a template of type ‘template<class ...> class ... Templates’, got ‘template<class A, int B, class C> struct Obj’
templ.cpp: In function ‘int main()’:
templ.cpp:23:8: error: type/value mismatch at argument 1 in template parameter list for ‘template<template<class ...> class ... Templates> struct Foo’
23 | Foo<Obj> foo;
| ^
templ.cpp:23:8: note: expected a template of type ‘template<class ...> class ... Templates’, got ‘template<class A, int B, class C> struct Obj’
It seems that it is not getting matched, although it doesn't look like it thinks the template<class ...> class ... Templates
is a syntax error, hence the parameter-parameter pack is parsing
Is this type of declaration (with some types, a constant value, then more types, or perhaps constant values at the end) unmatchable with variadic template template pack syntax? or perhaps I'm not using the syntax right
I modified the version to avoid non-types in declarations, but the problem persists:
template< template <class, class> class B, class A, class C>
struct Obj {
A a_obj;
//static constexpr int b_value = B;
B< C, A > b_obj;
C c_obj;
};
template< template<typename... > typename ... Templates >
struct Foo;
template<class A, class V>
struct Bar {
A a_obj;
//static constexpr int value = V;
V obj;
};
template<>
struct Foo<Obj> {
Obj<Bar, void*, float> obj;
};
int main() {
Foo<Obj> foo;
};
So it seems that is not that just non-types and types cannot be matches on a variadic pack, but any mixture of types and templates
I also tried adding an additional variadic pack:
template< template<typename... > typename ... Templates, class ... Types >
struct Foo;
But then I get:
error: parameter pack ‘template<class ...> class ... Templates’ must be at the end of the template parameter list
12 | template< template<typename... > typename ... Templates, class ... Types >
int B
is a non-type template parameter. You have to declare Templates
as template<class, auto, class> class
if you want it to work with that particular class template, or redefine Obj
to take a std::integral_constant
to pass a value encapsulated in a type:
template<class A, class B, class C>
struct Obj {
A a_obj;
static constexpr int b_value = B::value;
C c_obj;
};
template<template<class...> class... Templates>
struct Foo;
template<>
struct Foo<Obj> {
Obj<void*, std::integral_constant<int, 5>, float> obj;
};
int main() {
Foo<Obj> foo;
}