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コンテキスト変換のコンテキストが失われます。