2012-12-12 15 views
7

Ecco una versione semplificata di quello che sto cercando di faredisplay intero al momento della compilazione a static_assert()

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);*/ 

ma vorrei essere in grado di stampare il valore di primo :: nbElementFirstEnum e Seconda :: nbElementSecondEnum nel messaggio assert (come nella versione commentata che ovviamente non funziona). Ho provato a utilizzare la concatenazione delle macro con "#". Ho anche provato a utilizzare modelli variadic, recuperando con% 10 ogni numero e aggiungendo il carattere '0' al valore recuperato, ma tutto ciò che ottengo è un carattere di constexpr [].

Quindi la mia domanda è come posso ottenere i valori delle mie enumerazioni da stampare in una stringa letterale.

possibili duplicati:

C++11 static_assert: Parameterized error messages

Integrate type name in static_assert output?

L'argomento più interessante è stato questo: Printing sizeof(T) at compile time Ma io non voglio avere un avvertimento, o un codice decomment conoscere i valori .

risposta

4

Fondamentalmente funziona, anche se è possibile rompere con un piccolo sforzo (sommando V1 e V2 su un multiplo di 256). Quindi, penso che la tua soluzione sia più brutta ma ancora più robusta.

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); 

con uscita cercando come:

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" 

Per riferimento, questa versione originale dipendeva gcc stampare il messaggio static_assert anche quando la condizione booleana non viene compilato a tutti.

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); 

Nota Ho modificato le tue enumerazioni per essere fortemente digitate, perché altrimenti i nomi costanti enumerati si sono scontrati. Se si dispone di enumerazioni debolmente digitate, i valori First e Second passati alla macro devono denominare l'ambito che li include.

Ora, se io commento uno dei valori (in modo che le enumerazioni differenti formati), ottengo:

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" 

vedere come i valori interi vengono visualizzati nella errore di tipo incompleta, ed i nomi simbolici nell'asserzione statica?

+0

(sto usando gcc 4.7) E 'strano perché non è possibile convertire un enum fortemente tipizzato in un intero automaticamente devi usare un static_cast, tuttavia gcc si arresta all'errore "type incompleto" e non visualizza l'errore static_assert me Ssage. – b3nj1

+0

OK, ho appena eseguito il test rapidamente su una versione precedente (4.5.1). Se cambi la macro per usare 'static_cast (E1 :: M1)' ecc, come funziona? – Useless

+0

Beh, in realtà non abbiamo veramente bisogno del nome dell'enum da visualizzare, solo dei valori. Il problema è più che gcc si ferma all'errore "tipo incompleto" e non visualizza il messaggio di errore static_assert. Abbiamo ottenuto l'attivazione di un avviso in modo che venga sollevato static_assert. – b3nj1

1

Ecco la soluzione che ho trovato, otteniamo un messaggio di avviso con i valori e il messaggio di errore 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."); 

Ecco l'output 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. 

Si basa su questa soluzione: Printing sizeof(T) at compile time

+0

Anche con l'output 'static_assert', non sono sicuro che sia un pulitore o più leggibile del mio (onestamente, sembra piuttosto rumoroso). Tuttavia, è la tua domanda e le tue esigenze. – Useless

+0

Devo dire che è rumoroso, ma ho bisogno del messaggio di errore E dei valori da stampare ... Per ora questo è il meglio che devo fare (so che è un po 'brutto, ma sono aperto a qualsiasi altre soluzioni :). La tua soluzione è intelligente e buona ma il messaggio di errore non viene stampato:/Quale versione di gcc usi? (a proposito ti suggerisco di aggiungere i static_casts alla tua soluzione). – b3nj1

+0

Come ho detto, stavo usando 4.5.1 ... stampare il messaggio anche quando la condizione booleana non può essere compilata potrebbe essere stato un bug. – Useless

0

Il problema con le precedenti sono che si basano sulle segnalazioni che possono o non possono esistere su compilatori diversi e potrebbero non essere attivati ​​da tutti in ogni momento. (E in effetti, uno di loro non visualizza i valori di Clang con tutti gli avvisi attivati.)

Questa soluzione richiama le altre soluzioni qui, ma sfrutta il sistema di tipi, risultando quindi un errore effettivo per tutto il tempo, secondo lo standard C++. Sfortunatamente questo si ferma presto e non innesca lo stesso errore static_assert, che è l'unico lato negativo. Questo è stato testato su GCC 5.3 e Clang 3.7, senza attivare alcun avviso.

template <long V1, long V2> 
struct StaticAssertEquality 
{ 
    static constexpr void* NotEqualError() { return V1 + V2; } 
}; 

template <long V> 
struct StaticAssertEquality<V, V> 
{ 
    static constexpr bool NotEqualError = true; 
}; 

#define STATIC_ASSERT_LONG_EQUALITY(V1, V2)       \ 
    static_assert(             \ 
    StaticAssertEquality<static_cast<long>(V1),      \ 
         static_cast<long>(V2)>::NotEqualError,  \ 
    #V1 " != " #V2) 

// ... 

STATIC_ASSERT_LONG_EQUALITY(1, 2); 

Non funziona per l'intera gamma di unsigned long, ovviamente. Come ulteriore accorgimento di sicurezza, la macro potrebbe includere un secondo semplice static_assert(V1 == V2, #V1 " != " #V2); per catturare eventuali uguali differenze accidentali nella conversione del tipo.

uscita appare come questo per Clang:

file.cpp: error: cannot initialize return object of type 'void *' with an rvalue of type 'long' 
    static constexpr void* NotEqualError() { return V1 + V2; } 
                ^~~~~~~ 
file.cpp: note: in instantiation of member function 'StaticAssertEquality<1, 2>::NotEqualError' requested here 
    STATIC_ASSERT_LONG_EQUALITY(1, 2); 
^
file.cpp: note: expanded from macro 'STATIC_ASSERT_LONG_EQUALITY' 
           static_cast<long>(V2)>::NotEqualError,  \ 
                ^
1 error generated. 

E uscita con GCC:

file.cpp: In instantiation of 'static constexpr void* StaticAssertEquality<V1, V2>::NotEqualError() [with long V1 = 1; long V2 = 2]': 
file.cpp: required from here 
file.cpp: error: invalid conversion from 'long' to 'void*' [-fpermissive] 
    static constexpr void* NotEqualError() { return V1 + V2; } 
                 ^
g++.exe: failed with exit code 1 (00000001) 
+0

In effetti, il messaggio di errore static_assert non conta quasi adesso, perché non lo vedi mai .... –

1

In primo luogo una classe di supporto per stampare valori degli argomenti di template in output del compilatore:

template<size_t A, size_t B> struct TAssertEquality { 
    static_assert(A==B, "Not equal"); 
    static constexpr bool _cResult = (A==B); 
}; 

Quindi, dove è necessario testarlo:

messaggio di errore
static constexpr bool _cIsEqual = 
    TAssertEquality<First::nbElementFirstEnum, Second::nbElementSecondEnum>::_cResult; 

Il compilatore sarà simile:

nota: vedi riferimento al modello di classe istanziazione 'TAssertEquality < 32,64>' in fase di compilazione

0

Con C++11 e decltype:

#define UTILITY_PP_STRINGIZE_(x) #x 
#define UTILITY_PP_STRINGIZE(x) UTILITY_PP_STRINGIZE_(x) 

#define STATIC_ASSERT_TRUE(exp, msg) static_assert(::utility::StaticAssertTrue<decltype(exp), (exp)>::value, "expression: \"" UTILITY_PP_STRINGIZE(exp) "\": " msg) 
#define STATIC_ASSERT_TRUE1(exp, v1, msg) \ 
    static_assert(::utility::StaticAssertTrue<decltype(exp), (exp), \ 
        ::utility::StaticAssertParam<decltype(v1), (v1)> >::value, "expression: \"" UTILITY_PP_STRINGIZE(exp) "\": " msg) 
#define STATIC_ASSERT_TRUE2(exp, v1, v2, msg) \ 
    static_assert(::utility::StaticAssertTrue<decltype(exp), (exp), \ 
        ::utility::StaticAssertParam<decltype(v1), (v1)>, \ 
        ::utility::StaticAssertParam<decltype(v2), (v2)> >::value, "expression: \"" UTILITY_PP_STRINGIZE(exp) "\": " msg) 
#define STATIC_ASSERT_TRUE3(exp, v1, v2, v3, msg) \ 
    static_assert(::utility::StaticAssertTrue<decltype(exp), (exp), \ 
        ::utility::StaticAssertParam<decltype(v1), (v1)>, \ 
        ::utility::StaticAssertParam<decltype(v2), (v2)>, \ 
        ::utility::StaticAssertParam<decltype(v3), (v3)> >::value, "expression: \"" UTILITY_PP_STRINGIZE(exp) "\": " msg) 
#define STATIC_ASSERT_TRUE4(exp, v1, v2, v3, v4, msg) \ 
    static_assert(::utility::StaticAssertTrue<decltype(exp), (exp), \ 
        ::utility::StaticAssertParam<decltype(v1), (v1)>, \ 
        ::utility::StaticAssertParam<decltype(v2), (v2)>, \ 
        ::utility::StaticAssertParam<decltype(v3), (v3)>, \ 
        ::utility::StaticAssertParam<decltype(v4), (v4)> >::value, "expression: \"" UTILITY_PP_STRINGIZE(exp) "\": " msg) 

#define STATIC_ASSERT_FALSE(exp, msg) static_assert(::utility::StaticAssertFalse<decltype(exp), (exp)>::value, "expression: \"" UTILITY_PP_STRINGIZE(exp) "\": " msg) 
#define STATIC_ASSERT_FALSE1(exp, v1, msg) \ 
    static_assert(::utility::StaticAssertFalse<decltype(exp), (exp), \ 
        ::utility::StaticAssertParam<decltype(v1), (v1)> >::value, "expression: \"" UTILITY_PP_STRINGIZE(exp) "\": " msg) 
#define STATIC_ASSERT_FALSE2(exp, v1, v2, msg) \ 
    static_assert(::utility::StaticAssertFalse<decltype(exp), (exp), \ 
        ::utility::StaticAssertParam<decltype(v1), (v1)>, \ 
        ::utility::StaticAssertParam<decltype(v2), (v2)> >::value, "expression: \"" UTILITY_PP_STRINGIZE(exp) "\": " msg) 
#define STATIC_ASSERT_FALSE3(exp, v1, v2, v3, msg) \ 
    static_assert(::utility::StaticAssertFalse<decltype(exp), (exp), \ 
        ::utility::StaticAssertParam<decltype(v1), (v1)>, \ 
        ::utility::StaticAssertParam<decltype(v2), (v2)>, \ 
        ::utility::StaticAssertParam<decltype(v3), (v3)> >::value, "expression: \"" UTILITY_PP_STRINGIZE(exp) "\": " msg) 
#define STATIC_ASSERT_FALSE4(exp, v1, v2, v3, v4, msg) \ 
    static_assert(::utility::StaticAssertFalse<decltype(exp), (exp), \ 
        ::utility::StaticAssertParam<decltype(v1), (v1)>, \ 
        ::utility::StaticAssertParam<decltype(v2), (v2)>, \ 
        ::utility::StaticAssertParam<decltype(v3), (v3)>, \ 
        ::utility::StaticAssertParam<decltype(v4), (v4)> >::value, "expression: \"" UTILITY_PP_STRINGIZE(exp) "\": " msg) 

#define STATIC_ASSERT_EQ(v1, v2, msg) static_assert(::utility::StaticAssertEQ<decltype(v1), decltype(v2), (v1), (v2)>::value, "expression: \"" UTILITY_PP_STRINGIZE(v1) " == " UTILITY_PP_STRINGIZE(v2) "\": " msg) 
#define STATIC_ASSERT_NE(v1, v2, msg) static_assert(::utility::StaticAssertNE<decltype(v1), decltype(v2), (v1), (v2)>::value, "expression: \"" UTILITY_PP_STRINGIZE(v1) " != " UTILITY_PP_STRINGIZE(v2) "\": " msg) 
#define STATIC_ASSERT_LE(v1, v2, msg) static_assert(::utility::StaticAssertLE<decltype(v1), decltype(v2), (v1), (v2)>::value, "expression: \"" UTILITY_PP_STRINGIZE(v1) " <= " UTILITY_PP_STRINGIZE(v2) "\": " msg) 
#define STATIC_ASSERT_LT(v1, v2, msg) static_assert(::utility::StaticAssertLT<decltype(v1), decltype(v2), (v1), (v2)>::value, "expression: \"" UTILITY_PP_STRINGIZE(v1) " < " UTILITY_PP_STRINGIZE(v2) "\": " msg) 
#define STATIC_ASSERT_GE(v1, v2, msg) static_assert(::utility::StaticAssertGE<decltype(v1), decltype(v2), (v1), (v2)>::value, "expression: \"" UTILITY_PP_STRINGIZE(v1) " >= " UTILITY_PP_STRINGIZE(v2) "\": " msg) 
#define STATIC_ASSERT_GT(v1, v2, msg) static_assert(::utility::StaticAssertGT<decltype(v1), decltype(v2), (v1), (v2)>::value, "expression: \"" UTILITY_PP_STRINGIZE(v1) " > " UTILITY_PP_STRINGIZE(v2) "\": " msg) 


namespace utility 
{ 
    template <typename T, T v> 
    struct StaticAssertParam 
    { 
    }; 

    template <typename T, T v, typename ...Params> 
    struct StaticAssertTrue; 

    template <typename T, T v> 
    struct StaticAssertTrue<T, v> 
    { 
     static const bool value = (v ? true : false); 
    }; 

    template <typename T, T v, typename ...Params> 
    struct StaticAssertTrue 
    { 
     static const bool value = (v ? true : false); 
     static_assert(v ? true : false, "StaticAssertTrue with parameters failed."); 
    }; 

    template <typename T, T v, typename ...Params> 
    struct StaticAssertFalse; 

    template <typename T, T v> 
    struct StaticAssertFalse<T, v> 
    { 
     static const bool value = (v ? false : true); 
    }; 

    template <typename T, T v, typename ...Params> 
    struct StaticAssertFalse 
    { 
     static const bool value = (v ? false : true); 
     static_assert(v ? false : true, "StaticAssertFalse with parameters failed."); 
    }; 

    template <typename U, typename V, U u, V v> 
    struct StaticAssertEQ 
    { 
     static const bool value = (u == v); 
     static_assert(u == v, "StaticAssertEQ failed."); 
    }; 

    template <typename U, typename V, U u, V v> 
    struct StaticAssertNE 
    { 
     static const bool value = (u != v); 
     static_assert(u != v, "StaticAssertNE failed."); 
    }; 

    template <typename U, typename V, U u, V v> 
    struct StaticAssertLE 
    { 
     static const bool value = (u <= v); 
     static_assert(u <= v, "StaticAssertLE failed."); 
    }; 

    template <typename U, typename V, U u, V v> 
    struct StaticAssertLT 
    { 
     static const bool value = (u < v); 
     static_assert(u < v, "StaticAssertLT failed."); 
    }; 

    template <typename U, typename V, U u, V v> 
    struct StaticAssertGE 
    { 
     static const bool value = (u >= v); 
     static_assert(u >= v, "StaticAssertGE failed."); 
    }; 

    template <typename U, typename V, U u, V v> 
    struct StaticAssertGT 
    { 
     static const bool value = (u > v); 
     static_assert(u > v, "StaticAssertGT failed."); 
    }; 
} 

Utilizzo:

struct A 
{ 
    int a[4]; 
}; 

#define Float1 1.1f 
#define Float2 1.2f 

int main() 
{ 
    static const int a = 3; 
    static const long b = 5; 
    static const long c = 7; 
    static const long d = 9; 
    STATIC_ASSERT_TRUE4(a == b && c == d, a, b, c, d, "long_expression_with_multiple_integral_variables"); 

    #pragma message("----------------------------------------") 

    STATIC_ASSERT_TRUE(Float1 == Float2, "expression_with_floats"); 

    #pragma message("----------------------------------------") 

    STATIC_ASSERT_EQ(10, sizeof(A), "simple_integral_expression_1"); 

    #pragma message("----------------------------------------") 

    STATIC_ASSERT_EQ(11, sizeof(A), "simple_integral_expression_2"); 
    return 0; 
} 

MSVC2017:

source_file.cpp(72): error C2338: StaticAssertTrue with parameters failed. 
source_file.cpp(148): note: see reference to class template instantiation 'utility::StaticAssertTrue<bool,false,utility::StaticAssertParam<const int,3>,utility::StaticAssertParam<const long,5>,utility::StaticAssertParam<const long,7>,utility::StaticAssertParam<const long,9>>' being compiled 
source_file.cpp(148): error C2338: expression: "a == b && c == d": long_expression_with_multiple_integral_variables 
---------------------------------------- 
source_file.cpp(152): error C2338: expression: "1.1f == 1.2f": expression_with_floats 
---------------------------------------- 
source_file.cpp(95): error C2338: StaticAssertEQ failed. 
source_file.cpp(156): note: see reference to class template instantiation 'utility::StaticAssertEQ<int,size_t,10,16>' being compiled 
source_file.cpp(156): error C2338: expression: "10 == sizeof(A)": simple_integral_expression_1 
---------------------------------------- 
source_file.cpp(160): error C2338: expression: "11 == sizeof(A)": simple_integral_expression_2 

GCC 4.8.x:

<source>: In instantiation of 'struct utility::StaticAssertTrue<bool, false, utility::StaticAssertParam<const int, 3>, utility::StaticAssertParam<const long int, 5l>, utility::StaticAssertParam<const long int, 7l>, utility::StaticAssertParam<const long int, 9l> >': 
<source>:148:5: required from here 
<source>:72:9: error: static assertion failed: StaticAssertTrue with parameters failed. 
     static_assert(v ? true : false, "StaticAssertTrue with parameters failed."); 
     ^
<source>: In function 'int main()': 
<source>:18:5: error: static assertion failed: expression: "a == b && c == d": long_expression_with_multiple_integral_variables 
    static_assert(::utility::StaticAssertTrue<decltype(exp), (exp), \ 
    ^
<source>:148:5: note: in expansion of macro 'STATIC_ASSERT_TRUE4' 
    STATIC_ASSERT_TRUE4(a == b && c == d, a, b, c, d, "long_expression_with_multiple_integral_variables"); 
    ^
<source>:150:63: note: #pragma message: ---------------------------------------- 
    #pragma message("----------------------------------------") 
                  ^
<source>:4:41: error: static assertion failed: expression: "1.1f == 1.2f": expression_with_floats 
#define STATIC_ASSERT_TRUE(exp, msg) static_assert(::utility::StaticAssertTrue<decltype(exp), (exp)>::value, "expression: \"" UTILITY_PP_STRINGIZE(exp) "\": " msg) 
             ^
<source>:152:5: note: in expansion of macro 'STATIC_ASSERT_TRUE' 
    STATIC_ASSERT_TRUE(Float1 == Float2, "expression_with_floats"); 
    ^
<source>:154:63: note: #pragma message: ---------------------------------------- 
    #pragma message("----------------------------------------") 
                  ^
<source>: In instantiation of 'struct utility::StaticAssertEQ<int, long unsigned int, 10, 16ul>': 
<source>:156:5: required from here 
<source>:95:9: error: static assertion failed: StaticAssertEQ failed. 
     static_assert(u == v, "StaticAssertEQ failed."); 
     ^
<source>:44:41: error: static assertion failed: expression: "10 == sizeof(A)": simple_integral_expression_1 
#define STATIC_ASSERT_EQ(v1, v2, msg) static_assert(::utility::StaticAssertEQ<decltype(v1), decltype(v2), (v1), (v2)>::value, "expression: \"" UTILITY_PP_STRINGIZE(v1) " == " UTILITY_PP_STRINGIZE(v2) "\": " msg) 
             ^
<source>:156:5: note: in expansion of macro 'STATIC_ASSERT_EQ' 
    STATIC_ASSERT_EQ(10, sizeof(A), "simple_integral_expression_1"); 
    ^
<source>:158:63: note: #pragma message: ---------------------------------------- 
    #pragma message("----------------------------------------") 
                  ^
<source>: In instantiation of 'struct utility::StaticAssertEQ<int, long unsigned int, 11, 16ul>': 
<source>:160:5: required from here 
<source>:95:9: error: static assertion failed: StaticAssertEQ failed. 
     static_assert(u == v, "StaticAssertEQ failed."); 
     ^
<source>:44:41: error: static assertion failed: expression: "11 == sizeof(A)": simple_integral_expression_2 
#define STATIC_ASSERT_EQ(v1, v2, msg) static_assert(::utility::StaticAssertEQ<decltype(v1), decltype(v2), (v1), (v2)>::value, "expression: \"" UTILITY_PP_STRINGIZE(v1) " == " UTILITY_PP_STRINGIZE(v2) "\": " msg) 
             ^
<source>:160:5: note: in expansion of macro 'STATIC_ASSERT_EQ' 
    STATIC_ASSERT_EQ(11, sizeof(A), "simple_integral_expression_2"); 
    ^
Problemi correlati