1

有没有办法可以使用std::numeric_limits<T>::is_integerstd::numeric_limits<T>::is_specialized更改模板行为?

例如我可以这样做:

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

2 回答 2

8

你所拥有的目前是有效的。但是,您应该更喜欢使用 SFINAE,<type_traits>因为它会根据类型分派到不同的函数,而不是依赖于分支条件(可能会也可能不会优化)。

您可以使用std::enable_if执行以下操作:

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

现场演示

enable_if设置第二个参数 for 的原因int是为了节省我们的打字时间。如果int省略了,那么我们必须做typename = typename std::enable_if<std::is_integral<T>::value>::type而不是仅仅将其设置为0这样可以节省我们输入的几个字符。它们在所有意图和目的上都是等效的。

于 2014-08-11T20:07:15.573 回答
4

“显而易见”的答案是您可以使用类似std::enable_if.

例如:

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

这种方法的问题在于,这对于(作为示例)int参数来说是模棱两可的,因为numeric_limits<int>::is_specialized == true.

为了解决这个问题,我会简单地使用比numeric_limits, 个人更好的特征。您还可以使用布尔条件来测试您想要的确切条件:

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); }
于 2014-08-11T20:07:27.960 回答