std::numeric_limits as a Condition

此生再无相见时 提交于 2019-12-11 13:23:53

问题


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:


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); }



回答2:


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 optimised 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 characters to type. They're equivalent for all intents and purposes.



来源:https://stackoverflow.com/questions/25251380/stdnumeric-limits-as-a-condition

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!