2009-06-12 15 views
16

Nuestra implementación de afirmación en tiempo de compilación existente se basa en un índice de matriz negativo y proporciona una salida de diagnóstico deficiente en GCC. C++ 0x static_assert es una característica muy agradable, y la salida de diagnóstico que proporciona es mucho mejor. Sé que GCC ya ha implementado algunas características de C++ 0x. ¿Alguien sabe si static_assert está entre ellos y si es así desde qué versión de GCC?¿GCC tiene un tiempo de compilación incorporado?

+1

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

Respuesta

29

Según this page, gcc ha tenido static_assert desde 4.3.

+19

1 para no usar LMGTFY . – Johnsyweb

8

El siguiente código funciona como se esperaba con g ++ 4.4.0 cuando se compila con la bandera -std=c++0x:

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

muestra:

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

Si es necesario utilizar una versión de gcc que no lo hace apoyarlo se puede usar

#include <boost/static_assert.hpp> 

BOOST_STATIC_ASSERT(/* assertion */) 

Básicamente, lo que aumenta es esto:

declare (pero no definen!) Un

template< bool Condition > struct STATIC_ASSERTION_FAILURE; 

definir una especialización para el caso de que la afirmación sostiene:

template <> struct STATIC_ASSERTION_FAILURE<true> {}; 

Entonces se puede definir static_assert así:

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

El truco es que si la condición es falsa, el compilador necesita crear una instancia de la estructura

STATIC_ASSERTION_FAILURE<false> 

para calcular su tamaño, y esto falla porque no está definido.

+2

Me pregunto si hay alguna manera de hacer que aparezca un mensaje de error sensible de un truco como este ... – Thomas

+0

Según la documentación (http://www.boost.org/doc/libs/1_43_0/doc/html/boost_staticassert. html), este es uno de los objetivos de Boost.StaticAssert: "Uno de los objetivos de BOOST_STATIC_ASSERT es generar mensajes de error legibles. Estos inmediatamente le dicen al usuario que una biblioteca está siendo utilizada de una manera que no es compatible. " – Philipp

+0

Falta un paréntesis en' ... (Condición)>} ', probablemente debería ser' ... (Condición)>)} '. Traté de editar esto, pero fue rechazado ... – mbschenkel

1

Esto realmente no responde la pregunta, pero me gustan más las aseveraciones en tiempo de compilación basadas en el conmutador, p. Ej.

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

Funciona también en C y no solo en C++.

+4

Esta técnica tiene dos deficiencias. En primer lugar, dicha afirmación no se puede utilizar a nivel de clase o espacio de nombres. Y segundo, cuando la aserción tiene éxito, genera código ejecutable, inflando el binario. Le queda a su compilador de optimización para eliminarlo, y eso no está garantizado. :-( – VladLosev

1

siempre se puede jugar con las plantillas y al loro strutures a través de la plantilla -especialización. Así es como lo hace el impulso hasta donde yo sé. Esto es lo que uso como static_assert, es bastante directo.

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__ () 
} 

Ejemplo de uso

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

NSPR hace:

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

que falla si condition es falso porque declara una matriz de longitud negativa.

0

Tanto

BOOST_STATIC_ASSERT(x) 
    BOOST_STATIC_ASSERT_MSG(x, msg) 

utilizará el static_assert C++ 11 si su compilador soporta

Cuestiones relacionadas