答案 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,这与微优化有关。