これは基本的に機能しますが、少し努力すれば (V1 と V2 の合計を 256 の倍数にすることで) 破ることができます。したがって、あなたのソリューションは醜いと思いますが、それでもより堅牢です。
template <int V1, int V2> struct AssertEquality
{
static const char not_equal_warning = V1 + V2 + 256;
};
template <int V> struct AssertEquality<V, V>
{
static const bool not_equal_warning = 0;
};
#define ASSERT_EQUALITY(V1, V2) static_assert( \
AssertEquality<static_cast<int>(V1), \
static_cast<int>(V2)>::not_equal_warning == 0, \
#V1 " != " #V2 );
// ...
ASSERT_EQUALITY(First::nbElementFirstEnum, Second::nbElementSecondEnum);
出力は次のようになります。
g++ -std=c++0x -c chksz.cpp
chksz.cpp: In instantiation of ‘const char AssertEquality<3, 2>::not_equal_warning’:
chksz.cpp:40:124: instantiated from here
chksz.cpp:5:53: warning: overflow in implicit constant conversion
chksz.cpp:40:1: error: static assertion failed: "First::nbElementFirstEnum != Second::nbElementSecondEnum"
static_assert
参考までに、この元のバージョンは、ブール条件がまったくコンパイルされない場合でもメッセージを出力する gcc に依存していました。
template <typename Enum1, int Max1, typename Enum2, int Max2>
struct AssertSameSizeEnums;
template <typename Enum1, int EnumMax, typename Enum2>
struct AssertSameSizeEnums<Enum1, EnumMax, Enum2, EnumMax> {};
// only define the special case where Max1 and Max2 have the same integer value
#define ASSERT_SAME_SIZE_ENUMS(E1, M1, E2, M2) static_assert( \
sizeof(AssertSameSizeEnums<E1, E1::M1, E2, E2::M2>), \
#E1 "::" #M1 " != " #E2 "::" #M2 );
enum class First {
a, b, c, nbElementFirstEnum,
};
enum class Second {
a, b, c, nbElementSecondEnum,
};
ASSERT_SAME_SIZE_ENUMS(First, nbElementFirstEnum, Second, nbElementSecondEnum);
列挙定数名が衝突するため、列挙型を厳密に型指定するように変更したことに注意してください。弱く型付けされた列挙型がある場合、マクロに渡される and は、囲んでいるスコープに名前を付ける必要がありますFirst
。Second
ここで、値の 1 つをコメントアウトすると (列挙型のサイズが異なるため)、次のようになります。
g++ -std=c++0x -c chksz.cpp
chksz.cpp:25:113: error: invalid application of ‘sizeof’ to incomplete type ‘AssertSameSizeEnums<First, 3, Second, 2>’
chksz.cpp:25:1: error: static assertion failed: "First::nbElementFirstEnum != Second::nbElementSecondEnum"
不完全型エラーで整数値がどのように表示され、静的アサーションでシンボリック名がどのように表示されるかを確認してください。