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?
risposta
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"
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.
Mi chiedo se c'è un modo per far apparire un messaggio di errore ragionevole da un trucco come questo ... – Thomas
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
C'è una parentesi mancante in' ... (Condizione)>} ", dovrebbe probabilmente essere' ... (Condizione)>)} '. Ho provato a modificare questo, ma è stato respinto ... – mbschenkel
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++.
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
Se avete un gcc di età superiore o utilizzare un vecchio standard C++, o utilizzare C, quindi è possibile emulare static_assert come descritto qui: http://www.pixelbeat.org/programming/gcc/static_assert.html
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
}
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.
Sia
BOOST_STATIC_ASSERT(x)
BOOST_STATIC_ASSERT_MSG(x, msg)
utilizzerà lo static_assert C++ 11 se il compilatore supporta
http://en.wikichip.org/wiki/c/static_assertions –