Given a template
template <int n>
void f(){...};
I know I can specialize it for specific values of n
by doing:
template <>
void f<2>(){...};
But, is there a method which allows me to specialize it for all positive n
?
I thought of doing the following
template <int n>
void f<n>(){
int dummy[n]; //invalid for n < 0
...
};
So for n<0
this code is invalid and the compiler would resort to the previous definition. Unfortunately, all I get is a redefinition of 'void f<n>()'
error.
Note: I'm guessing this is probably not supported by the standard. I'm asking if there isn't some method (maybe some template metaprogramming) to achieve this effect.
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.
Class templates are generally used to implement containers. A class template is instantiated by passing a given set of types to it as template arguments. The C++ Standard Library contains many class templates, in particular the containers adapted from the Standard Template Library, such as vector .
A class template must be declared before any instantiation of a corresponding template class. A class template definition can only appear once in any single translation unit. A class template must be defined before any use of a template class that requires the size of the class or refers to members of the class.
One option would be to use another level of indirection. Define an auxiliary template that takes in two arguments - the number n
and a bool
representing whether or not n
is negative, then specialize that template for when n
is negative. Then, have your f
function instantiate the template with the right arguments.
For example:
template <int n, bool isNegative> struct fImpl {
static void f() {
/* ... code for when n is positive ... */
}
};
template <int n> struct fImpl<n, true> {
static void f() {
/* ... code for when n is negative ... */
}
};
template <int n> void f() {
fImpl<n, (n < 0)>::f();
}
Another option is to use SFINAE overloading and the std::enable_if
template class from C++11 (or Boost's equivalent);
template <int n> void f(typename std::enable_if<(n < 0)>::type* = 0) {
/* ... n is negative ... */
}
template <int n> void f(typename std::enable_if<(n >= 0)>::type* = 0) {
/* ... n is positive ... */
}
Each of these functions will only be available for overload resolution if n
has the proper sign, so the correct version will always be called.
Hope this helps!
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