¿Podría dar un ejemplo en el que static_assert(...)
('C ++ 11') resolvería el problema con elegancia?
Estoy familiarizado con el tiempo de ejecución assert(...)
. ¿Cuándo debería preferirlo static_assert(...)
al regular assert(...)
?
Además, boost
hay algo llamado BOOST_STATIC_ASSERT
, ¿es lo mismo que static_assert(...)
?
Respuestas:
La parte superior de mi cabeza...
Suponiendo que
SomeLibrary::Version
se declare como una constante estática, en lugar de ser#define
d (como cabría esperar en una biblioteca de C ++).En contraste con tener que compilar realmente
SomeLibrary
su código, vincular todo y ejecutar el ejecutable solo entonces, descubra que pasó 30 minutos compilando una versión incompatible deSomeLibrary
.@Arak, en respuesta a su comentario: sí, puede
static_assert
simplemente sentarse donde sea, por lo que parece:fuente
static_assert
en un contexto de no ejecución? Parece un ejemplo muy bonito :)static_assert
. Si no se conocerá la condición hasta que se ejecute el programa, utiliceassert
.La aserción estática se usa para hacer aserciones en tiempo de compilación. Cuando la aserción estática falla, el programa simplemente no se compila. Esto es útil en diferentes situaciones, como, por ejemplo, si implementa alguna funcionalidad por código que depende críticamente de que el
unsigned int
objeto tenga exactamente 32 bits. Puedes poner una aserción estática como estaen su código. En otra plataforma, con un
unsigned int
tipo de letra de tamaño diferente, la compilación fallará, lo que llamará la atención del desarrollador sobre la parte problemática del código y le aconsejará que lo vuelva a implementar o lo vuelva a inspeccionar.Para otro ejemplo, es posible que desee pasar algún valor integral como un
void *
puntero a una función (un truco, pero útil a veces) y desea asegurarse de que el valor integral quepa en el punteroEs posible que desee que el activo de ese
char
tipo esté firmadoo que la división integral con valores negativos se redondea hacia cero
Y así.
En muchos casos, las aserciones en tiempo de ejecución se pueden usar en lugar de las aserciones estáticas, pero las aserciones en tiempo de ejecución solo funcionan en tiempo de ejecución y solo cuando el control pasa sobre la aserción. Por esta razón, una aserción de tiempo de ejecución fallida puede permanecer inactiva, sin ser detectada durante períodos de tiempo prolongados.
Por supuesto, la expresión en aserción estática tiene que ser una constante en tiempo de compilación. No puede ser un valor en tiempo de ejecución. Para los valores de tiempo de ejecución, no tiene otra opción que utilizar el ordinario
assert
.fuente
static_assert
específicamente a C ++ 11. Lostatic_assert
anterior es solo una implementación abstracta de aserción estática. (Yo personalmente uso algo así en el código C). Mi respuesta pretende ser sobre el propósito general de las aserciones estáticas y su diferencia con las aserciones en tiempo de ejecución.unsigned int
. Esto no está garantizado por el estándar. Una variable de tipounsigned int
podría ocupar legalmente 32 bits de memoria, dejando 16 de ellos sin usar (y por lo tanto la macroUINT_MAX
sería igual a65535
). Entonces, la forma en que describe la primera afirmación estática ("unsigned int
objeto que tiene exactamente 32 bits") es engañosa. Para que coincida con su descripción, esta afirmación debe ser incluido también:static_assert(UINT_MAX >= 0xFFFFFFFFu)
.Lo uso para asegurarme de que mis suposiciones sobre el comportamiento del compilador, los encabezados, las bibliotecas e incluso mi propio código sean correctas. Por ejemplo, aquí verifico que la estructura se ha empaquetado correctamente al tamaño esperado.
En un envoltorio de clase
stdio.h
'sfseek()
, he tomado algunos atajos conenum Origin
y cheque que esos atajos se alinean con las constantes definidas porstdio.h
Usted debe preferir
static_assert
másassert
cuando el comportamiento se define en tiempo de compilación y no en tiempo de ejecución, como los ejemplos que he dado anteriormente. Un ejemplo en el que este no es el caso incluiría la verificación de parámetros y códigos de retorno.BOOST_STATIC_ASSERT
es una macro pre-C ++ 0x que genera código ilegal si no se cumple la condición. Las intenciones son las mismas, aunquestatic_assert
están estandarizadas y pueden proporcionar mejores diagnósticos del compilador.fuente
BOOST_STATIC_ASSERT
es un contenedor multiplataforma para lastatic_assert
funcionalidad.Actualmente estoy usando static_assert para hacer cumplir "Conceptos" en una clase.
ejemplo:
Esto provocará un error de tiempo de compilación si no se cumple alguna de las condiciones anteriores.
fuente
Un uso de
static_assert
podría ser asegurarse de que una estructura (que es una interfaz con el mundo exterior, como una red o un archivo) tenga exactamente el tamaño esperado. Esto detectaría casos en los que alguien agrega o modifica un miembro de la estructura sin darse cuenta de las consecuencias. Elstatic_assert
lo recogería y alertaría al usuario.fuente
En ausencia de conceptos, se puede usar
static_assert
para la verificación de tipos en tiempo de compilación simple y legible, por ejemplo, en plantillas:fuente
Esto no responde directamente a la pregunta original, pero constituye un estudio interesante sobre cómo hacer cumplir estas comprobaciones de tiempo de compilación antes de C ++ 11.
El Capítulo 2 (Sección 2.1) de Diseño C ++ moderno de Andrei Alexanderscu implementa esta idea de aserciones en tiempo de compilación como esta
Compare la macro STATIC_CHECK () y static_assert ()
fuente
Se
static_assert
puede usar para prohibir el uso de ladelete
palabra clave de esta manera:#define delete static_assert(0, "The keyword \"delete\" is forbidden.");
Todo desarrollador moderno de C ++ puede querer hacer eso si quiere usar un recolector de basura conservador usando solo clases y estructuras que sobrecargan al operador new para invocar una función que asigna memoria en el montón conservador del recolector de basura conservador que se puede inicializar y crear instancias invocando alguna función que haga esto al principio de la
main
función.Por ejemplo, todo desarrollador de C ++ moderno que quiera utilizar el recolector de basura conservador de Boehm-Demers-Weiser, al principio de la
main
función, escribirá:GC_init();
Y en todas
class
y cada una de lasstruct
sobrecargas deoperator new
esta manera:Y ahora que
operator delete
ya no se necesita, porque el recolector de basura conservador de Boehm-Demers-Weiser es responsable de liberar y desasignar cada bloque de memoria cuando ya no se necesita, el desarrollador quiere prohibir ladelete
palabra clave.Una forma es sobrecargar la de
delete operator
esta manera:Pero esto no se recomienda, porque el desarrollador de C ++ moderno sabrá que invocó por error el
delete operator
tiempo de ejecución, pero es mejor saberlo pronto en tiempo de compilación.Entonces, en mi opinión, la mejor solución para este escenario es usar
static_assert
como se muestra al comienzo de esta respuesta.Por supuesto que esto también se puede hacer
BOOST_STATIC_ASSERT
, pero creo questatic_assert
es mejor y debería preferirse más siempre.fuente