I'm learning C++11 variadic template and created a template struct to calculate the max number of a given list and tried:
#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;
}
but g++ complains:
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> {};
I can make it run by adding a simple declaration ahead:
template <int...>
struct max;
and change the first template above to:
template <int a, int b, int... cs>
struct max<a, b, cs...>: ...
I referred to cppreference: https://en.cppreference.com/w/cpp/language/partial_specialization#Partial_ordering but I cannot find any useful explanation for my case.
The problem may come from the last template (max<a>
) with only one template parameter, which is not a specialized version of the primary one.
So my question is:
Why max<a>
cannot be matched? Is there any rules or standards dealing with this?
=================================================================
okay, I found the C++ standards (Document No. N4659) that says:
[ 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 ]
So I think any partial specialized template that does not specialize from the base/primary one is considered to be an error, even though sometimes we can generate some non-specialized forms of expression from normal ones.
When you define a class template as:
template <int a, int b, int... cs> struct max { ... };
The following is a valid specialization.
template <int a, int b> struct max<a, b> { ... };
However, the following is not.
template <int a> struct max<a> { ... };
since the base class template requires at least two template parameters.
Not an answer, but why not simply...
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> {};
...?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With