我正在学习 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...>: ...
我提到了cpp偏好:https://en.cppreference.com/w/cpp/language/partial_specialization#Partial_ordering 但我找不到任何有用的解释来解释我的情况。
问题可能来自只有一个模板参数的最后一个模板(max<a>
(,这不是主模板的专用版本。
所以我的问题是:
为什么max<a>
无法匹配?是否有任何规则或标准来处理这个问题?
=====================================================================================================================================================================================================
好的,我找到了C++标准(文件编号 N4659(,上面写着:
[ 注意:类模板的部分特化由 查找主类模板,然后考虑所有部分 该模板的专业化。如果 using 声明命名一个类 模板,在 使用声明实际上是可见的,因为主模板 可见 (17.5.5(。— 尾注 ]
因此,我认为任何不从基本/主要模板专用的部分专用模板都被认为是错误的,即使有时我们可以从正常模板生成一些非专用的表达形式。
将类模板定义为:
template <int a, int b, int... cs> struct max { ... };
以下是有效的专业化。
template <int a, int b> struct max<a, b> { ... };
但是,以下不是。
template <int a> struct max<a> { ... };
因为基类模板至少需要两个模板参数。
不是答案,但为什么不简单地...
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> {};
...?
您收到该错误的原因是,模板的每次调用都必须首先与基本模板匹配,并且专用化仅在此之后启动。
您的基本模板应该匹配任意数量的参数,并且没有实现(因为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;
}