可变参数模板模板参数包的问题

Issue with variadic template template parameter pack

考虑以下示例:

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;

};

这对我来说是失败的(g++ 7.2,-std=c++17 有以下错误:

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’

它似乎没有匹配,虽然它看起来不像它认为 template<class ...> class ... Templates 是语法错误,因此参数-参数包正在解析

这种类型的声明(有一些类型,一个常量值,然后是更多类型,或者最后可能是常量值)是否与可变参数模板模板包语法无法匹配?或者也许我没有使用正确的语法

编辑

我修改了版本以避免声明中出现非类型,但问题仍然存在:

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;

};

所以似乎不仅仅是非类型和类型不能在可变参数包上匹配,而是类型和模板的任何混合

我还尝试添加一个额外的可变参数包:

template< template<typename... > typename ... Templates, class ... Types >
struct Foo;

但后来我得到:

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 是非类型模板参数。如果您希望它与特定的 class 模板一起使用,则必须将 Templates 声明为 template<class, auto, class> class,或者重新定义 Obj 以采用 std::integral_constant 来传递值封装在一个类型中:

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;
}

Try it on godbolt.org.