如何使用参数包和非类型模板值执行部分模板专业化?

How to perform partial template specialization with a parameter pack and non-type template value?

在尝试 时,我编写了这个部分模板专业化:

template <typename array_wrapper> struct Test1;
template <std::size_t... A> struct Test1<any_type<std::array<std::size_t, sizeof...(A)>{A...}>> {}; //(2)

当我尝试使用 Test1Test2 的部分模板专业化时,这会导致编译错误 <Expression> has incomplete type and cannot be defined;因此——据我所知——用法 (3) 与定义 (2) 不匹配:

int main() {
  Test1<any_type<std::array<std::size_t, 2>{1, 2}>> a; // (3)
}

虽然我不明白为什么会这样。在试验该示例时,我意识到当我 'hiding' 我的 any_type 结构中参数包的内容时会发生这种情况:

#include <array>

template <auto f> struct any_type;

template <typename array_wrapper> struct Test1;
template <std::size_t... A> struct Test1<any_type<std::array<std::size_t, sizeof...(A)>{A...}>> {};

template <typename array_wrapper> struct Test2;
template <int... A> struct Test2<any_type<std::get<0>(A...)>> {};

template <typename array_wrapper> struct Test3;
template <int A> struct Test3<any_type<A>> {};

int main() {
  //Test1<any_type<std::array<std::size_t, 2>{1, 2}>> a;
  //Test2<any_type<1>> b;
  Test3<any_type<1>> ok;
}

测试 1 和测试 2 失败并出现同样的错误,测试 3 工作正常。为什么在前两种情况下部分模板特化 'fail'?据我了解,声明提供了 'interface' 以便使用该结构,并且专业化中的参数与实际提供的参数相匹配。

代码 可以找到代码 here.

编译选项: 我使用 g++-10.0 (GCC) 10.0.1 20200124 (experimental) 并通过 g++ -std=c++2a file.cc 编译,需要 c++2a 因为我使用非类型模板参数。

模板参数可以从一组有限的模式中推导出来。对于模板非类型参数,该集合只是(来自 [temp.deduct.type]/8):

  • type[i]
  • template-name<i>(其中模板名称指的是 class 模板)
  • TT<i>

...就是这样。您的 Test3 匹配第二种形式,而其他两个根本不匹配。

尚不清楚 Test2 示例的工作原理。 Test1 示例可能是我们想要考虑的东西,因为非类型模板参数的使用在 C++20 之后激增,但它不是当前有效的东西。