在C ++ 11中定义可能/不太可能的宏的正确方法如下:
#define LIKELY(condition) __builtin_expect(static_cast<bool>(condition), 1)
#define UNLIKELY(condition) __builtin_expect(static_cast<bool>(condition), 0)
不同于[[likely]]
,此方法与所有C ++版本兼容,但依赖于非标准扩展__builtin_expect
。
当这些宏以这种方式定义时:
#define LIKELY(condition) __builtin_expect(!!(condition), 1)
这可能会更改if
语句的含义并破坏代码。考虑以下代码:
#include <iostream>
struct A
{
explicit operator bool() const { return true; }
operator int() const { return 0; }
};
#define LIKELY(condition) __builtin_expect((condition), 1)
int main() {
A a;
if(a)
std::cout << "if(a) is true\n";
if(LIKELY(a))
std::cout << "if(LIKELY(a)) is true\n";
else
std::cout << "if(LIKELY(a)) is false\n";
}
及其输出:
if(a) is true
if(LIKELY(a)) is false
如您所见,LIKELY的定义!!
用作强制转换来bool
破坏的语义if
。
这里的关键不在于operator int()
并且operator bool()
应该是相关的。这是个好习惯。
而是使用!!(x)
而不是static_cast<bool>(x)
丢失C ++ 11上下文转换的上下文。