dbb*_*bbd 3 c++ boost assertions
我正在使用一个可能很危险的宏:
#define REMAINDER(v, size) ((v) & (size -1))
Run Code Online (Sandbox Code Playgroud)
显然它假设大小是2的幂.
我想确保大小确实是2的幂,但在编译时.(在运行时测试很容易,但不是我想要的).
对我来说一个充分的测试就是大小总是一个常数(从不变量).
我会用BOOST_STATIC_ASSERT,但我无法弄清楚如何使用它来满足我的需要.
首先要做的事情是:不需要微观优化.任何具有优化功能的合适编译器都将转换a % b为该构造,b而编译时常量实际上是2的幂.
然后在特定断言上,您可以使用相同的构造来断言它[*]:
BOOST_STATIC_ASSERT( !(size & (size-1)) );
Run Code Online (Sandbox Code Playgroud)
[*]请注意,正如Matthieu M指出的那样,只有size在无符号类型的情况下才有效.应该断言 - 在编译时不能断言参数是非负的较小要求:
BOOST_STATIC_ASSERT( (X(0)-1) > X(0) ); // where X is the type of the argument
Run Code Online (Sandbox Code Playgroud)
最后评论后编辑:
你错过了这一点.要使静态断言宏起作用,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 %
//...
};
Run Code Online (Sandbox Code Playgroud)
同时声明在编译时保持不变量对于效率很重要,模糊代码不是:只需将模运算保留在原位,因为编译器将优化:
std::size_t hash_map::index_of( std::size_t hash ) const {
return hash % size;
}
Run Code Online (Sandbox Code Playgroud)
因为它size是一个编译时常量,并且它是2的幂(你之前断言过),优化器将转换%为优化操作,而代码仍然需要维护它的人可读.
编辑:除非你有分析证明这是你的代码中的瓶颈,并且你的编译器没有适当地优化(v%8),只需编写明显的代码.
否则,因为你在这里处理整数,你可以使用模板而不是宏吗?然后你应该能够在模板内部静态断言,这样它就会在它被错误地实例化时标记出来.
例如:
template <int size>
int remainder(int v)
{
BOOST_STATIC_ASSERT(!(size & (size - 1)));
return v & (size -1);
};
Run Code Online (Sandbox Code Playgroud)