I have a variadic template function which calls itself to determine the largest number in a list (constituted by the templatized arguments). I am trying to make a specialization for when the parameter pack is empty so I can just return the number at the front of the list, but I don't know how to do that. I am just becoming familiar with variadic templates and template specialization, but this is what I have so far:
#include <string>
#include <iostream>
using namespace std;
template <int N, int... N2>
int tmax() {
return N > tmax<N2...>() ? N : tmax<N2...>();
}
template <int N>
int tmax() {
return N;
}
int main() {
cout << tmax<32, 43, 54, 12, 23, 34>();
}
However, this produces the following error:
test.cpp: In function ‘int tmax() [with int N = 34, int ...N2 = {}]’:
test.cpp:9:45: instantiated from ‘int tmax() [with int N = 23, int ...N2 = {34}]’
test.cpp:9:45: instantiated from ‘int tmax() [with int N = 12, int ...N2 = {23, 34}]’
test.cpp:9:45: instantiated from ‘int tmax() [with int N = 54, int ...N2 = {12, 23, 34}]’
test.cpp:9:45: instantiated from ‘int tmax() [with int N = 43, int ...N2 = {54, 12, 23, 34}]’
test.cpp:9:45: instantiated from ‘int tmax() [with int N = 32, int ...N2 = {43, 54, 12, 23, 34}]’
test.cpp:18:39: instantiated from here
test.cpp:9:45: error: no matching function for call to ‘tmax()’
test.cpp:9:45: error: no matching function for call to ‘tmax()’
I have also tried this, just to see if it would work (although it introduces the number 0 to the list randomly so that it can't ever return a number less than 0):
template <int N, int... N2>
int tmax() {
return N > tmax<N2...>() ? N : tmax<N2...>();
}
template <>
int tmax<>() {
return 0;
}
However, in addition to the errors mentioned above, I get this error:
error: template-id ‘tmax<>’ for ‘int tmax()’ does not match any template declaration
So what should I do to get this working?
I am using g++ 4.5.2 with the -std=c++0x
flag.
In C++ this can be achieved using template parameters. A template parameter is a special kind of parameter that can be used to pass a type as argument: just like regular function parameters can be used to pass values to a function, template parameters allow to pass also types to a function.
The act of creating a new definition of a function, class, or member of a class from a template declaration and one or more template arguments is called template instantiation. The definition created from a template instantiation is called a specialization.
Variadic templates are class or function templates, that can take any variable(zero or more) number of arguments. In C++, templates can have a fixed number of parameters only that have to be specified at the time of declaration. However, variadic templates help to overcome this issue.
Parameter packs (C++11) A parameter pack can be a type of parameter for templates. Unlike previous parameters, which can only bind to a single argument, a parameter pack can pack multiple parameters into a single parameter by placing an ellipsis to the left of the parameter name.
I see two mistakes using clang.
Put the overload taking a single int first.
Make things unambiguous for lists of length 1. Recall that variadic lists can have zero size and when they do, it seems to me you have an ambiguity.
This compiles and runs correctly for me:
#include <iostream>
using namespace std;
template <int N>
int tmax() {
return N;
}
template <int N, int N1, int... N2>
int tmax() {
return N > tmax<N1, N2...>() ? N : tmax<N1, N2...>();
}
int main() {
cout << tmax<32, 43, 54, 12, 23, 34>();
}
54
Personally, I'd prefer using static class members over functions for this sort of thing:
template <int... N> struct max;
template <int N, int... M> struct max<N, M...> {
static const int value = max<N, max<M...>::value>::value;
};
template <int N, int M> struct max<N, M> {
static const int value = N > M ? N : M;
};
int main()
{
return max<1,2,3>::value;
}
Update: Using ildjarn's suggestion, here's the less verbose version:
#include <type_traits>
template <int... N> struct max;
template <int N, int... M> struct max<N, M...>
: std::integral_constant<int, max<N, max<M...>::value>::value> { };
template <int N, int M> struct max<N, M>
: std::integral_constant<int, (N > M ? N : M)> { };
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