5

I want to have a template to select on numeric types, but I want to also have a global type template too. I tried to apply the solution for this question, but it didn't work:

template<typename T, typename ... Types> void myFct(T arg1, Types ... rest) { /*do stuff*/ } template<typename T, typename = typename std::enable_if<std::is_arithmetic<T>::value, T>::type, typename ... Types> void myFct(T arg1, Types ... rest) { /* do stuff */ } 

because now I have two functions with the same header. What's the right way to do something like:

template<typename T, typename ... Types> void myFct(T arg1, Types ... rest) { if (isNumeric(T)) doNumericStuff(); else doStuff(); } 
2
  • Have you tried inverting the condition for enable_if and slapping it into the first template (the one for general purpose Ts)? Its worse solution than tag dispatch, but its a solution. Commented May 21, 2015 at 17:24
  • Yeah I tryed, i got error code C2995 function template has already been defined, cause myFct(T, Types) have 2 definition. Commented May 21, 2015 at 17:28

2 Answers 2

6

There's probably better ways of doing this, but the simplest way to me is to just slap the enable_if onto the return type:

template<typename T, typename ... Types> typename std::enable_if< std::is_arithmetic<T>::value >::type myFct(T arg1, Types ... rest) { /*do numeric stuff*/ } template<typename T, typename ... Types> typename std::enable_if< !std::is_arithmetic<T>::value >::type myFct(T arg1, Types ... rest) { /*do non-numeric stuff*/ } 

This gets very unwieldy once you have more than just two mutually exclusive options, but this will definitely work.

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

1 Comment

Thanks, that does exactly what I want. I am just not sure how the typename as the return type works... Will go check this.
5

Update for C++17

if constexpr discards the unused branch so this is easier (live link):

void myFct() { } template<typename T, typename... Ts> void myFct(T arg1, Ts... rest) { if constexpr (std::is_arithmetic<T>{}) { std::cout << "squared: " << arg1*arg1 << '\n'; } else { std::cout << "not-number\n"; } myFct(rest...); // recurse } 

You can use tag-dispatching here, and overload the implementation function, since your "do stuff" only seems to be concerned with one object at a time.

template <typename T> void do_stuff(T arg, std::true_type) { std::cout << "number\n"; } template <typename T> void do_stuff(T arg, std::false_type) { std::cout << "not-number\n"; } void myFct() { } template<typename T, typename... Ts> void myFct(T arg1, Ts... rest) { // is_arithmetic will derive either true_type or false_type do_stuff(arg1, std::is_arithmetic<T>{}); myFct(rest...); // recurse } 

This is a typical pattern to get something like a "static if"

If I call this with myFct(1, std::string{}, 2.0); I get the output

number not-number number 

2 Comments

Was a good idea. Will keep in mind those true_type and false_type. It might be useful someday. =D
the error messages from tag dispatch tend to be less insane than the ones from SFINAE also

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.