15

This is definitely a trivial question, but I couldn't figure out how to do this.

I have a template function, say template <unsigned int N> void my_function(). Now, I have two different implementations for my_function, the first should be used if N is bigger than, say, 100, the other if N is smaller than that.

I tried to use SFINAE like this:

template <unsigned int N, typename = enable_if <N >= 100> :: type> my_function() { // First implementation } template <unsigned int N, typename = enable_if <N < 100> :: type> my_function() { // Second implementation } 

But that's declaring the same function two times. Then I tried doing something like

template <unsigned int N, bool = (N >= 100)> my_function(); 

And then implementing the two functions with the two different values of the boolean. No success, since it is a partial specialization.

Then I tried to wrap N as a struct parameter, and the bool in the function call, but it is specializing a member function before specializing the class, which cannot be done.

Is there a reasonable way to do this?

3 Answers 3

12

Try this instead:

#include <type_traits> #include <iostream> template <unsigned int N, typename std::enable_if <N >= 100> :: type* = nullptr> void my_function() { std::cout << "N >= 100" << std::endl; } template <unsigned int N, typename std::enable_if <N < 100> :: type* = nullptr> void my_function() { std::cout << "N < 100" << std::endl; } int main() { my_function<42>(); my_function<100>(); } 

Template default parameters do not participate in the overload (and hence SFINAE does not apply). On the other hand, in the snippet above, the dependent template non-type parameter is on the left hand side of the assignment, so SFINAE kicks in.

Sign up to request clarification or add additional context in comments.

Comments

5

If you don't like enable_if for some reason, you can always go for tag dispatch:

#include <type_traits> class low {}; class high {}; template <int N, class T> void func(T, low) { // version for high N } template <int N, class T> void func(T, high) { // version for low N } template <int N, class T> void func(T val) { func<N>(val, std::conditional_t<(N>=100), high, low>{}); } int main() { func<3>(3.14159); // low version func<256>("Yo"); // high version } 

In this case, we could restrict the tags to simple things like true_type and false_type, but in general this might be an alternative approach.

Comments

2

You may use SFINAE on return type:

template <unsigned int N> enable_if_t<(N >= 100)> my_function() { // First implementation } template <unsigned int N> enable_if_t<(N < 100)> my_function() { // Second implementation } 

currently, you have only template <unsigned int N, typename T> with different default type for T.

For the partial specialization, you may forward to structure:

template <unsigned int N, bool = (N >= 100)> struct my_function_impl; template <unsigned int N> struct my_function_impl<N, true> { void operator () const { /* First implementation */} }; template <unsigned int N> struct my_function_impl<N, false> { void operator () const { /* Second implementation */} }; template <unsigned int N> void my_function() { my_function_impl<N>{}(); } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.