C++ 模板:无法匹配可变参数 class 模板中的最后一个模板

C++ template: cannot match the last template in variadic class template

我正在学习 C++11 可变参数模板并创建了一个模板结构来计算给定列表的最大数量并尝试过:

#include <iostream>
#include <type_traits>

template <int a, int b, int... cs>
struct max: std::integral_constant<int, (a>b? max<a, cs...>::value: max<b, cs...>::value)> {};
template <int a, int b>
struct max<a, b>: std::integral_constant<int, (a>b? max<a>::value: max<b>::value)> {};
template <int a>
struct max<a>: std::integral_constant<int, a> {};

int main() {
  std::cout << max<2,1,5,7>::value << std::endl;
  return 0;
}

但是 g++ 抱怨:

test.cc:7:58: error: wrong number of template arguments (1, should be at least 2)
 struct max<a, b>: std::integral_constant<int, (a>b? max<a>::value : max<b>::value)> {};

test.cc:9:13: error: wrong number of template arguments (1, should be at least 2)
 struct max<a>: std::integral_constant<int, a> {};

我可以通过在前面添加一个简单的声明来实现 运行:

template <int...>
struct max;

并将上面的第一个模板更改为:

template <int a, int b, int... cs>
struct max<a, b, cs...>: ...

我提到了 cppreference:https://en.cppreference.com/w/cpp/language/partial_specialization#Partial_ordering 但我找不到任何对我的案例有用的解释。

问题可能出在只有一个模板参数的最后一个模板 (max<a>) 上,该模板不是主要模板的专用版本。

所以我的问题是:

为什么max<a>无法匹配?是否有处理此问题的规则或标准?

============================================= ====================

好的,我发现 C++ 标准(文档编号 N4659)说:

[ Note: Partial specializations of class templates are found by looking up the primary class template and then considering all partial specializations of that template. If a using-declaration names a class template, partial specializations introduced after the using-declaration are effectively visible because the primary template is visible (17.5.5). — end note ]

所以我认为任何不从 base/primary 特化的部分特化模板都被认为是错误的,即使有时我们可以从正常的表达形式生成一些非特化形式。

您收到该错误的原因是模板的每次调用都必须首先匹配基本模板,并且只有在那之后才开始专门化。

你的基础模板应该匹配任意数量的参数,并且没有实现(因为 max<>::value 没有意义),并且有一个可变参数,所有其他 类 是那。

#include <iostream>
#include <type_traits>

template<int... cs>
struct max;

template <int a, int b, int... cs>
struct max<a, b, cs...>: std::integral_constant<int, (a>b? max<a, cs...>::value: max<b, cs...>::value)> {};
template <int a, int b>
struct max<a, b>: std::integral_constant<int, (a>b? max<a>::value: max<b>::value)> {};
template <int a>
struct max<a>: std::integral_constant<int, a> {};

int main() {
  std::cout << max<2,1,5,7>::value << std::endl;
  return 0;
}

不是答案,但为什么不干脆...

template <int a, int... bs>
struct max : std::integral_constant<int,
   (a > max<bs...>::value ? a : max<bs...>::value)> {};

template <int a>
struct max<a> : std::integral_constant<int, a> {};

...?

当您将 class 模板定义为:

template <int a, int b, int... cs> struct max { ... };

以下是有效的专业化。

template <int a, int b> struct max<a, b> { ... };

然而,下面不是。

template <int a> struct max<a> { ... };

因为基础 class 模板需要至少两个模板参数。