2009-06-12 10 views
16

L'implementazione dell'attestazione in fase di compilazione esistente si basa su un indice di array negativo e fornisce uno scarso output di diagnostica su GCC. C++ 0x static_assert è una funzionalità molto bella e l'output diagnostico che fornisce è molto meglio. So che GCC ha già implementato alcune funzionalità di C++ 0x. Qualcuno sa se static_assert è tra questi e se è poi da che versione GCC?GCC ha un tempo di compilazione incorporato?

+1

http://en.wikichip.org/wiki/c/static_assertions –

risposta

29

In base a this page, gcc ha avuto static_assert dal 4.3.

+19

+1 per non usare LMGTFY . – Johnsyweb

8

Il seguente codice funziona come previsto con g ++ 4.4.0 quando si compila con la bandiera -std=c++0x:

int main() { 
    static_assert(false, "that was false"); 
} 

visualizza:

x.cpp: In function 'int main()': 
x.cpp:2: error: static assertion failed: "that was false" 
16

Se è necessario utilizzare una versione di gcc che non lo fa supportarlo è possibile utilizzare

#include <boost/static_assert.hpp> 

BOOST_STATIC_ASSERT(/* assertion */) 

Fondamentalmente, ciò che aumenta è questo:

Declare (ma non definiscono!) Un

template< bool Condition > struct STATIC_ASSERTION_FAILURE; 

Definire una specializzazione per il caso che l'affermazione contiene:

template <> struct STATIC_ASSERTION_FAILURE<true> {}; 

Poi si può definire STATIC_ASSERT in questo modo:

#define STATIC_ASSERT(Condition) \ 
    enum { dummy = sizeof(STATIC_ASSERTION_FAILURE< (bool)(Condition) > } 

Il trucco è che se Condizione è falso il compilatore deve istanziare la struttura

STATIC_ASSERTION_FAILURE<false> 

per calcolarne le dimensioni e questo non riesce poiché non è definito.

+2

Mi chiedo se c'è un modo per far apparire un messaggio di errore ragionevole da un trucco come questo ... – Thomas

+0

Secondo la documentazione (http://www.boost.org/doc/libs/1_43_0/doc/html/boost_staticassert. html), questo è uno degli obiettivi di Boost.StaticAssert: "Uno degli scopi di BOOST_STATIC_ASSERT è generare messaggi di errore leggibili. Questi dicono immediatamente all'utente che una libreria viene utilizzata in un modo che non è supportato. " – Philipp

+0

C'è una parentesi mancante in' ... (Condizione)>} ", dovrebbe probabilmente essere' ... (Condizione)>)} '. Ho provato a modificare questo, ma è stato respinto ... – mbschenkel

1

Questo in realtà non risponde alla domanda, ma mi piacciono le asserzioni in fase di compilazione basate su switch-case, ad es.

#define COMPILE_TIME_ASSERT(cond) do { switch(0) { case 0: case cond: ; } } while (0) 

Funziona anche in C e non solo in C++.

+4

Questa tecnica ha due difetti. In primo luogo, tale asserzione non può essere utilizzata a livello di classe o spazio dei nomi. E in secondo luogo, quando l'asserzione ha successo, genera codice eseguibile, gonfiando il binario. Viene lasciato al compilatore di ottimizzazione per rimuoverlo, e questo non è garantito. :-( – VladLosev

1

si può sempre giocare con modelli e inesistenti strutures tramite template -specializzazione. Questo è il modo in cui il boost lo fa per quanto ne so. Questo è quello che uso come static_assert, è piuttosto semplice.

namespace Internal 
{ 
template<bool x> struct SASSERT_F; 
template<  > struct SASSERT_F <true> {}; 
template<int x> struct SASSERT_P  {}; 
#define STATIC_ASSERT(B)   \ 
    typedef Internal::SASSERT_P <(\ 
    sizeof (Internal::SASSERT_F <(\ 
     ((B)? true : false)) >) \ 
           )> \ 
     StaticAssert##__LINE__ () 
} 

esempio di utilizzo

int main(int argc, char **argv) 
{ 
    static_assert(sizeof(int) == 1)   // Error 
    static_assert(sizeof(int) == sizeof(int)) // OK 
} 
1

NSPR fa:

#define PR_STATIC_ASSERT(condition) \ 
    extern void pr_static_assert(int arg[(condition) ? 1 : -1]) 

che fallisce se condition è falso perché dichiara una matrice di lunghezza negativa.

0

Sia

BOOST_STATIC_ASSERT(x) 
    BOOST_STATIC_ASSERT_MSG(x, msg) 

utilizzerà lo static_assert C++ 11 se il compilatore supporta