【问题标题】:std::numeric_limits as a Conditionstd::numeric_limits 作为条件
【发布时间】:2014-08-11 19:59:28
【问题描述】:

有没有办法可以使用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 );
    }
}

【问题讨论】:

  • 有更好的特性可以做到这一点。

标签: c++ templates c++11 numeric-limits


【解决方案1】:

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

您可以使用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);
}

Live Demo

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

【讨论】:

  • enable_if 的第二个参数始终是int。我不明白为什么。
  • @JonathanMee 第二个参数的int 在那里,因此您可以将其设置为等于某个值(在本例中为0),这样您就不必重复输入typename,即typename = typename std::enable_if&lt;condition&gt;::type
  • 因此,如果我的理解正确,您可能希望这些 = 0 中的每一个都不同(例如 = 1= 2= 2= 3),以便您可以重复使用它们在另一个方法模板中?
  • @JonathanMee 不,条件必须不同且明确。您可以将数字设置为任何您想要的。
  • 为什么不直接使用enable_if 来定义返回类型呢?这样打字的次数要少得多(template&lt;typename T&gt; typename std::enable_if&lt;std::is_integral&lt;T&gt;::value&gt;::type foo...)。
【解决方案2】:

“显而易见”的答案是您可以使用 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&lt;int&gt;::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); }

【讨论】:

  • 如果我的函数因返回类型而异,这似乎会有所帮助。我希望它们因参数类型而异。
  • @Praetorian 在了解这里的std::enable_if 是定义返回类型为void 之后,我尝试了这段代码。我可以让它在 VS2012 上编译。也许我在滥用@Rapptz 的解决方案,因为我无法理解template 参数中的相等性在做什么。
  • @JonathanMee 不相等,= 0int 类型的非类型模板参数的默认模板参数。顺便说一句,试图在 cmets 中将我 ping 到其他答案是行不通的。我只是看到这个,因为你在新问题中链接到这个问题:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-12-09
  • 2017-06-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-11
相关资源
最近更新 更多