在编译时计算积分base-2对数的正确方法是什么?

ein*_*ica 4 logarithm constants idiomatic constexpr c++11

我有一些积极的恒定值来自不同的库而不是我的,称之为the_val.现在,我想log_of_the_val成为楼层(log_2(the_val)) - 不是用C++代码说话 - 我当然希望在编译时发生这种情况.

现在,使用gcc,我可以做类似的事情

decltype(the_val) log_of_the_val = sizeof(the_val) * CHAR_BIT - __builtin_clz(the_val) - 1;
Run Code Online (Sandbox Code Playgroud)

我觉得这应该有用(长度 - 标题零的数量).否则,我可以自己实现一个constexpr函数,但我敢打赌,我可以在编译时使用其他更简单,更便携的东西.......问题是,那会是什么?

eca*_*mur 7

最直接的解决方案是使用std::log2from <cmath>,但是没有指定为constexpr - 它是在gcc下,但不是在clang下.(实际上,libstdc ++ std::log2调用__builtin_log2,这是gcc下的constexpr.)

__builtin_clz 是gcc和clang下的constexpr,所以你可能想要使用它.

完全可移植的解决方案是编写一个递归的constexpr积分log2:

constexpr unsigned cilog2(unsigned val) { return val ? 1 + cilog2(val >> 1) : -1; }
Run Code Online (Sandbox Code Playgroud)

  • @einpoklum`log2(0)`是一个错误,但它简化了返回`-1`的实现.另一种方法是终止`1`的递归,并将`std :: domain_error`抛给`0`:`constexpr unsigned cilog2(unsigned val){return val> 1?1 + cilog2(val >> 1):val == 1?0:抛出std :: domain_error {"cilog2(0)"}; }` (2认同)