2

Is there a way that I can use std::numeric_limits<T>::is_integer and std::numeric_limits<T>::is_specialized to change template behavior?

For example can I do this:

template < typename T >
void foo( const T& bar )
{
    if( std::numeric_limits< T >::is_integer )
    {
        isInt( bar );
    }
    else if( std::numeric_limits< T >::is_specialized )
    {
        isFloat( bar );
    }
    else
    {
        isString( bar );
    }
}
1
  • There are better traits to do this. Commented Aug 11, 2014 at 20:03

2 Answers 2

8

What you have is currently valid. However, you should prefer to use SFINAE and <type_traits> instead since it would dispatch to a different function based on the type rather than rely on a branch condition (which may or may not be optimized away).

You can use std::enable_if to do the following:

template<typename T, 
         typename std::enable_if<std::is_integral<T>::value, int>::type = 0>
void foo(const T& t) {
    isInt(t);
}

template<typename T, 
         typename std::enable_if<std::is_floating_point<T>::value, int>::type = 0>
void foo(const T& t) {
    isFloat(t);
}

template<typename T, 
         typename std::enable_if<!std::is_integral<T>::value && 
                                 !std::is_floating_point<T>::value, int>::type = 0>
void foo(const T& t) {
    isString(t);
}

Live Demo

The reason that the second parameter for enable_if is set to int is to save us some typing. If the int is left out then we'd have to do typename = typename std::enable_if<std::is_integral<T>::value>::type instead of just setting it to 0 which would save us a couple of characters to type. They're equivalent for all intents and purposes.

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

7 Comments

That second parameter to enable_if you always have as an int. I don't understand why.
@JonathanMee The int for the second parameter is there so you can set it equal to something (in this case 0) that way you don't have to type typename redundantly, i.e. typename = typename std::enable_if<condition>::type
So if I'm understanding you correctly you'd probably want each of these = 0 to be different (like = 1, = 2, and = 3) so you could reuse them in another method template?
@JonathanMee No, the condition just has to be different and unambiguous. You can set the number to whatever you want.
Why don't you just use enable_if to define the return type? It is much less typing that way (template<typename T> typename std::enable_if<std::is_integral<T>::value>::type foo…).
|
4

The "obvious" answer is that you could use something like std::enable_if.

For example:

template<typename T>
typename std::enable_if<std::numeric_limits<T>::is_integer, void>::type
    foo(const T &bar) { isInt(bar); }
template<typename T>
typename std::enable_if<std::numeric_limits<T>::is_specialized, void>::type
    foo(const T &bar) { isFloat(bar); }

The problem with this approach is that this is ambiguous for (as an example) an int parameter, since numeric_limits<int>::is_specialized == true.

To resolve this, I would simply use a better trait than numeric_limits, personally. You can also use boolean conditions to test for the exact condition you want:

template<typename T>
typename std::enable_if<std::numeric_limits<T>::is_specialized && !std::numeric_limits<T>::is_integer, void>::type
    foo(const T &bar) { isFloat(bar); }

3 Comments

It looks like this would help if my functions varied by return type. I want them to vary by parameter type.
@Praetorian After understanding that the std::enable_if here was defining the return type as void, I tried this code out. I am able to get this to compile on VS2012. Perhaps I'm misusing @Rapptz's solution since I can't understand what the equality in the template parameters is doing.
@JonathanMee It's not equality, the = 0 is the default template argument for the non-type template parameter of type int. BTW, trying to ping me in comments to other answers doesn't work. I only saw this because you linked to this question in your new question :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.