5

我遇到了一个问题,我确信它很容易解决,但我不知所措......

我有一个执行以下代码的模板:

T value     = d;
if ( std::numeric_limits< T >::is_signed )
{
    if ( value < 0 )
    {
        *this += _T( "-" );
        value = -(signed)value;
    }
}

现在,出于显而易见的原因,当将此代码编译为无符号类型时,GCC 会给我一个警告(由于数据类型的范围有限,比较总是错误的)。我完全理解这背后的原因,我进行了 numeric_limits 检查,看看我是否可以让编译器闭嘴(它适用于 MSVC)。唉,在 GCC 下我得到了警告。有什么办法(除了禁用我什至不知道你是否可以用 GCC 做的警告)来修复这个警告吗?无论如何,代码永远不会被调用,我认为优化器也会将其编译出来,但我无法摆脱警告。

有人可以给我一个解决方案吗?

干杯!

4

4 回答 4

5

更简单的解决方案:

template <typename T> inline bool isNegative(T value) {
  return std::numeric_limits< T >::is_signed && value < 0; // Doesn't trigger warning.
}

T value     = d;
if ( isNegative(value) ) // Doesn't trigger warning either.
{
    *this += _T( "-" );
    value = -1 * value;
}
于 2010-06-29T12:18:32.757 回答
3

有关真正的解决方案,请参阅https://stackoverflow.com/a/8658004/274937,它允许逐个抑制-Wtype-limits警告。简而言之,只需将生成警告的每个比较包装到一个虚拟函数中。

于 2011-12-28T16:03:46.790 回答
3

有人可以给我一个解决方案吗?

没有什么革命性的,但我通常通过超载来做到这一点。沿着这些思路:

//Beware, brain-compiled code ahead!
template< bool B >
struct Bool { const static bool result = B; }

template< typename T >
void do_it(T& , Bool<false> /*is_signed*/)
{
  // nothing to do for unsigned types
}

template< typename T >
void do_it(T& value, Bool<true> /*is_signed*/)
{
    if ( value < 0 ) {
        *this += _T( "-" );
        value = -(signed)value;
    }
}

template< typename T >
void do_something(T& value)
{
  do_it(value, Bool<std::numeric_limits< T >::is_signed>() );
}

如果可以使用类模板代替函数模板,则可以使用特化代替重载。(没有函数模板部分特化,这使得特化函数模板有点麻烦。)

于 2010-06-29T11:14:06.240 回答
2

您可以像这样专门化您的功能:

template <bool S> 
void manipulate_sign(T&) {}

template <> 
void manipulate_sign<true>(T& value) {
  if ( value < 0 )
  {
    *this += _T( "-" );
    value = -(signed)value;
  }
}

//then call like this:
manipulate_sign<std::numeric_limits< T >::is_signed>();

只是禁用警告可能会更好。

于 2010-06-29T11:15:13.350 回答