时间:2011-01-06 18:32:01

标签: c++ warnings

11 个答案:

答案 0 :(得分:2)

答案 1 :(得分:2)

-Wtype-limits 警告可以通过将与常量的比较包装到虚拟二进制函数中来逐个抑制,该函数接受要比较的操作数。在这种情况下,上面的代码可以转换为:

// Dummy function, which suppresses -Wtype-limits warnings
// where appropriate.
template <typename R>
static inline bool dummy_less(const R a, const R b)
{
  return (a < b);
}

template <typename R>
static inline unsigned count(const R num)
{
    if (dummy_less(num, 10))        return 1;
    else if (dummy_less(num, 100))  return 2;
    // ...
    else                            return 20;
}

编译器应该很容易将常量传播到虚函数中。

答案 2 :(得分:1)

答案 3 :(得分:1)

答案 4 :(得分:1)

答案 5 :(得分:1)

答案 6 :(得分:0)

答案 7 :(得分:0)

// Beware. brain-compiled code ahead!
namespace {
  inline unsigned count_long_long(unsigned long long num)
    if (num < 10000000000ULL)          return 10;
    else if (num < 100000000000ULL)         return 11;
    else if (num < 1000000000000ULL)        return 12;
    else if (num < 10000000000000ULL)       return 13;
    else if (num < 100000000000000ULL)      return 14;
    else if (num < 1000000000000000ULL)     return 15;
    else if (num < 10000000000000000ULL)    return 16;
    else if (num < 100000000000000000ULL)   return 17;
    else if (num < 1000000000000000000ULL)  return 18;
    else if (num < 10000000000000000000ULL) return 19;
    else                                    return 20;
  }
  template <typename R>
  inline unsigned count_long_long(const R num) {return 20;}
}

template <typename R>
inline unsigned count(const R num)
{
  if(num < 10)                    return 1;
  else if (num < 100)             return 2;
  else if (num < 1000)            return 3;
  else if (num < 10000)           return 4;
  else if (num < 100000)          return 5;
  else if (num < 1000000)         return 6;
  else if (num < 10000000)        return 7;
  else if (num < 100000000)       return 8;
  else if (num < 1000000000)      return 9;
  else return count_long_long(num);
}

答案 8 :(得分:0)

也许在编译时生成适当数量的比较?

#include <limits>

template <class T, int power>
struct pow10
{
    static const T value = 10 * pow10<T, power - 1>::value;
};

template <class T>
struct pow10<T, 0>
{
    static const T value = 1;
};

template <class T, int power_of_ten, bool recurse>
struct digit_counter
{
    unsigned count(T value) const
    {
        if (value < pow10<T, power_of_ten>::value) return power_of_ten;
        else return digit_counter<T, power_of_ten + 1, power_of_ten < std::numeric_limits<T>::digits10>().count(value);
    }
};

template <class T, int power_of_ten>
struct digit_counter<T, power_of_ten, false>
{
    unsigned count(T ) const
    {
        return   std::numeric_limits<T>::digits10 + 1;
    }
};

template <class T>
unsigned count(T value)
{
    return digit_counter<T, 1, (std::numeric_limits<T>::digits10 > 1)>().count(value);
}

优化后,它应该产生与原始二进制文件完全相同的二进制文件。

答案 9 :(得分:0)

因为它是一个内联函数,为什么你不信任编译器并使它成为

static inline unsigned count(const R unsigned long long);

然后它应该将其任何整数类型的参数提升为unsigned long long(标准学生会选择我,但我假设它会)并运行给定的代码,这给出了相同的结果就像你的模板一样。

在实践中,编译器应该(如果你被打扰的话,测试它)如果他们发现输入具有受限范围,则删除不必要的条件,这在任何情况下都是你在模板化情况下所希望的。模板的额外成本是来自&lt; num&gt;的一次促销。对于unsigned long long,再次假设你的编译器是个白痴。

答案 10 :(得分:0)

我的方法存在问题。

您的代码未经过优化,因为您执行线性搜索而不是二进制搜索。

一个简单的例子,假设您的数字在0到65535之间(包括0和65535),您应该使用以下算法:

if num < 1000:
  if num < 100:
     if num < 10: return 1
     return 2
  return 3

if num < 10000: return 4
return 5

这是一个二元搜索,在最坏的情况下最多有3个比较(数字为1或2位),所有其他只有2个比较。

这意味着存在整数大小的信息,不应轻易丢弃。

namespace detail
{
  template <int Size> struct number_bits {};

  template <typename Unsigned>
  number_bits< sizeof(Unsigned)*8 > count_number_bits(Unsigned)
  {
    return number_bits< sizeof(Unsigned)*8 >();
  }

  template <typename Unsigned>
  unsigned number_digits_helper(Unsigned t, number_bits<8>);

  template <typename Unsigned>
  unsigned number_digits_helper(Unsigned t, number_bits<16>);

  template <typename Unsigned>
  unsigned number_digits_helper(Unsigned t, number_bits<32>);

  template <typename Unsigned>
  unsigned number_digits_helper(Unsigned t, number_bits<64>);

  template <typename Unsigned>
  unsigned number_digits_helper(Unsigned t, number_bits<128>);

  template <typename Unsigned>
  unsigned number_digits_helper(Unsigned t, number_bits<256>);

} // namespace detail


template <typename Unsigned>
unsigned number_digits(Unsigned t)
{
  static_assert(!std::numeric_limits<Unsigned>::is_signed, "t is signed");
  return detail::number_digits_helper(t, detail::count_number_bits(t));
}

现在,你可以完全优化每个无符号类型位数的每个例程(我知道,没有真正的原因,每个大小会有多个无符号类型,不是吗?)

为了在知道大小时进行优化,我建议您查看Bit Twiddling Hacks,这与微优化有关。