我正在使用一个可能有危险的宏:
#define REMAINDER(v, size) ((v) & (size -1))
显然它假定大小是 2 的幂。
我想确保大小确实是 2 的幂,但在编译时。 (在运行时测试很容易,但不是我想要的)。
对我来说,一个充分的测试是大小始终是一个常数(绝不是变量)。
我会使用 BOOST_STATIC_ASSERT
,但我不知道如何使用它来满足我的需要。
最佳答案
首先要做的是:不需要微优化。当 b
是一个编译时间常量,实际上是 2 的幂时,任何启用了优化的体面的编译器都会将 a % b
转换成该结构。
然后在特定断言上,您可以使用相同的构造来断言它 [*]:
BOOST_STATIC_ASSERT( !(size & (size-1)) );
[*] 请注意,正如 Matthieu M 指出的那样,这仅在 size
是无符号类型时才有效。并且应该断言——参数为非负的较小要求不能在编译时断言:
BOOST_STATIC_ASSERT( (X(0)-1) > X(0) ); // where X is the type of the argument
在最后评论后编辑:
你没有捕获要点。要使静态断言宏起作用,size
必须是编译时常量。如果它是一个编译时常量,那么只需在定义常量时断言,这也是最好的地方,因为它将用作文档,并将指向需要修改的精确代码点:
template <typename N>
class hash_map {
public:
const std::size_t size = N;
BOOST_STATIC_ASSERT( !(size & (size-1) ) ); // N must be power of 2 for fast %
//...
};
与此同时,断言在编译时保持不变量对于 boost 效率很重要,但混淆代码并不重要:只需保留模运算,因为编译器会优化:
std::size_t hash_map::index_of( std::size_t hash ) const {
return hash % size;
}
因为 size
是一个编译时间常量,它是二的幂(你之前断言过)优化器会将 %
转换为优化操作,而需要维护它的人仍然可以阅读代码。
关于C++ 编译时断言,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5183307/