17

これが私がやろうとしていることの簡略版です

enum First
{
    a,
    b,
    c,
    nbElementFirstEnum,
};
enum Second
{
    a,
    b,
    c,
    nbElementSecondEnum,
};

static_assert(
    First::nbElementFirstEnum == Second::nbElementSecondEnum,
    "Not the same number of element in the enums.");
/*static_assert(  
    First::nbElementFirstEnum == Second::nbElementSecondEnum, 
    "Not the same number of element in the enums." + First::nbElementFirstEnum + " " + Second::nbElementSecondEnum);*/

しかし、アサーションメッセージにFirst::nbElementFirstEnumとSecond::nbElementSecondEnumの値を出力できるようにしたいと思います(明らかに機能しないコメント付きバージョンのように)。「#」でマクロ連結を使用してみました。また、可変個引数テンプレートを使用して、各数値を%10で取得し、取得した値に「0」文字を追加しようとしましたが、取得するのはconstexprchar[]だけです。

だから私の質問は、列挙型の値を文字列リテラルで出力する方法を教えてください。

重複の可能性:

C ++ 11 static_assert:パラメーター化されたエラーメッセージ

タイプ名をstatic_assert出力に統合しますか?

最も興味深いトピックはこれでした: コンパイル時にsizeof(T)を出力し ますが、値を知るための警告やコメント解除コードは必要ありません。

4

6 に答える 6

6

これは基本的に機能しますが、少し努力すれば (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 は、囲んでいるスコープに名前を付ける必要がありますFirstSecond

ここで、値の 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"

不完全型エラーで整数値がどのように表示され、静的アサーションでシンボリック名がどのように表示されるかを確認してください。

于 2012-12-12T10:54:12.483 に答える
3

これが私が見つけた解決策です。値と static_assert エラーメッセージを含む警告メッセージが表示されます。

template<int N>
struct TriggerOverflowWarning
{
    static constexpr char value() { return N + 256; }
};

template <int N, int M, typename Enable = void>
struct CheckEqualityWithWarning
{
    static constexpr bool value = true;
};

template <int N, int M>
struct CheckEqualityWithWarning<N, M, typename std::enable_if<N != M>::type>
{
    static constexpr bool value = (TriggerOverflowWarning<N>::value() == TriggerOverflowWarning<M>::value());
};

static constexpr int a = 9;
static constexpr int b = 10;

static_assert(CheckEqualityWithWarning<a, b>::value, "Mismatch.");

gcc の出力は次のとおりです。

g++ -std=c++11 -c test.cpp
test.cpp: In instantiation of 'static constexpr char TriggerOverflowWarning<N>::value() [with int N = 10]':
test.cpp:18:112:   required from 'constexpr const bool CheckEqualityWithWarning<9, 10>::value'
test.cpp:24:51:   required from here
test.cpp:6:52: warning: overflow in implicit constant conversion [-Woverflow]
test.cpp: In instantiation of 'static constexpr char TriggerOverflowWarning<N>::value() [with int N = 9]':
test.cpp:18:112:   required from 'constexpr const bool CheckEqualityWithWarning<9, 10>::value'
test.cpp:24:51:   required from here
test.cpp:6:52: warning: overflow in implicit constant conversion [-Woverflow]
test.cpp:24:5: error: static assertion failed: Mismatch.

これは、このソリューションに基づいています:コンパイル時に sizeof(T) を印刷する

于 2012-12-12T12:36:13.930 に答える