¿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, boosthay algo llamado BOOST_STATIC_ASSERT, ¿es lo mismo que static_assert(...)?

Respuestas:
La parte superior de mi cabeza...
Suponiendo que
SomeLibrary::Versionse declare como una constante estática, en lugar de ser#defined (como cabría esperar en una biblioteca de C ++).En contraste con tener que compilar realmente
SomeLibrarysu 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_assertsimplemente sentarse donde sea, por lo que parece:$ g ++ --std = c ++ 0x a.cpp a.cpp: 7: error: la aserción estática falló: "Foo :: bar es demasiado pequeña :("fuente
static_asserten 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 intobjeto tenga exactamente 32 bits. Puedes poner una aserción estática como estaen su código. En otra plataforma, con un
unsigned inttipo 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
chartipo 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_assertespecíficamente a C ++ 11. Lostatic_assertanterior 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 intpodría ocupar legalmente 32 bits de memoria, dejando 16 de ellos sin usar (y por lo tanto la macroUINT_MAXsería igual a65535). Entonces, la forma en que describe la primera afirmación estática ("unsigned intobjeto 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 Originy cheque que esos atajos se alinean con las constantes definidas porstdio.hUsted debe preferir
static_assertmásassertcuando 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_ASSERTes una macro pre-C ++ 0x que genera código ilegal si no se cumple la condición. Las intenciones son las mismas, aunquestatic_assertestán estandarizadas y pueden proporcionar mejores diagnósticos del compilador.fuente
BOOST_STATIC_ASSERTes un contenedor multiplataforma para lastatic_assertfuncionalidad.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_assertpodrí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_assertlo recogería y alertaría al usuario.fuente
En ausencia de conceptos, se puede usar
static_assertpara 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_assertpuede usar para prohibir el uso de ladeletepalabra 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
mainfunción.Por ejemplo, todo desarrollador de C ++ moderno que quiera utilizar el recolector de basura conservador de Boehm-Demers-Weiser, al principio de la
mainfunción, escribirá:GC_init();Y en todas
classy cada una de lasstructsobrecargas deoperator newesta manera:Y ahora que
operator deleteya 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 ladeletepalabra clave.Una forma es sobrecargar la de
delete operatoresta manera:Pero esto no se recomienda, porque el desarrollador de C ++ moderno sabrá que invocó por error el
delete operatortiempo 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_assertcomo se muestra al comienzo de esta respuesta.Por supuesto que esto también se puede hacer
BOOST_STATIC_ASSERT, pero creo questatic_assertes mejor y debería preferirse más siempre.fuente