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