4

我正在学习 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-declaration 命名类模板,则在 using-declaration 之后引入的部分特化有效可见,因为主模板是可见的 (17.5.5)。——尾注]

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

4

3 回答 3

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

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

于 2018-06-06T20:14:12.863 回答
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;
}
于 2018-06-06T20:09:22.717 回答
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> {};

...?

于 2018-06-06T20:09:29.327 回答