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

时间:2018-06-06 20:01:19

标签: c++ c++11 templates variadic partial-ordering

我正在学习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)说:

  

[注意:类模板的部分特化可以通过以下方式找到   查找主要类模板和然后考虑所有部分   该模板的特化。如果using声明命名一个类   模板,部分专业化后引入   使用声明是有效可见的,因为主要模板   是可见的(17.5.5)。 - 结束说明]

所以我认为任何不从基础/主要模板专门化的部分专用模板都被认为是一个错误,即使有时我们可以从正常模式中生成一些非专业的表达形式。<​​/ p>

3 个答案:

答案 0 :(得分:4)

将类模板定义为:

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

以下是有效的专业化。

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

但是,以下情况并非如此。

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

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

答案 1 :(得分:2)

您收到该错误的原因是模板的每次调用必须首先与基本模板匹配,然后专门化才会启动。

您的基本模板应匹配任意数量的参数,并且没有实现(因为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;
}

答案 2 :(得分:2)

不是答案,但为什么不简单......

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

...