constexpr, static_assert, y en línea
Previamente pregunté sobrefunción de sobrecarga en función de si los argumentos sonconstexpr
. Estoy tratando de evitar la respuesta decepcionante a esa pregunta para hacer una función de afirmación más inteligente. Esto es más o menos lo que estoy tratando de hacer:
inline void smart_assert (bool condition) {
if (is_constexpr (condition))
static_assert (condition, "Error!!!");
else
assert (condition);
}
Básicamente, la idea es que una verificación en tiempo de compilación siempre es mejor que una verificación en tiempo de ejecución si es posible verificar en tiempo de compilación. Sin embargo, debido a cosas como la alineación y el plegado constante, no siempre puedo saber si es posible realizar una verificación del tiempo de compilación. Esto significa que puede haber casos dondeassert (condition)
compila hastaassert(false)
y el código solo está esperando que lo ejecute y ejecute esa ruta antes de que descubra que hay un error.
Por lo tanto, si hubiera alguna forma de verificar si la condición es una constexpr (debido a las optimizaciones en línea u otras), podría llamarstatic_assert
cuando sea posible, y retroceder en un tiempo de ejecución de lo contrario. Afortunadamente, gcc tiene la intrínseca__builtin_constant_p (exp)
, que devuelve true siexp
es un constexpr. No sé si otros compiladores tienen este intrínseco, pero esperaba que esto solucionara mi problema. Este es el código que se me ocurrió:
#include <cassert>
#undef IS_CONSTEXPR
#if defined __GNUC__
#define IS_CONSTEXPR(exp) __builtin_constant_p (exp)
#else
#define IS_CONSTEXPR(exp) false
#endif
// TODO: Add other compilers
inline void smart_assert (bool const condition) {
static_assert (!IS_CONSTEXPR(condition) or condition, "Error!!!");
if (!IS_CONSTEXPR(condition))
assert (condition);
}
#undef IS_CONSTEXPR
losstatic_assert
se basa en el comportamiento de corto circuito deor
. SiIS_CONSTEXPR
es verdad, entoncesstatic_assert
puede ser utilizado, y la condición es!true or condition
, que es lo mismo que solocondition
. SiIS_CONSTEXPR
es falso, entoncesstatic_assert
no se puede utilizar, y la condición es!false or condition
, que es lo mismo quetrue
y elstatic_assert
se ignora Si elstatic_assert
no se puede comprobar porquecondition
no es un constexpr, luego agrego un tiempo de ejecuciónassert
a mi código como último esfuerzo. Sin embargo, esto no funciona, gracias ano poder usar argumentos de función en unastatic_assert
, incluso si los argumentos sonconstexpr
.
En particular, esto es lo que sucede si intento compilar con gcc:
// main.cpp
int main () {
smart_assert (false);
return 0;
}
g++ main.cpp -std=c++0x -O0
Todo está bien, se compila normalmente. No hay en línea sin optimización, por lo queIS_CONSTEXPR
es falso y elstatic_assert
se ignora, así que solo tengo un tiempo de ejecuciónassert
declaración (que falla). Sin embargo,
[david@david-desktop test]$ g++ main.cpp -std=c++0x -O1
In file included from main.cpp:1:0:
smart_assert.hpp: In function ‘void smart_assert(bool)’:
smart_assert.hpp:12:3: error: non-constant condition for static assertion
smart_assert.hpp:12:3: error: ‘condition’ is not a constant expression
Tan pronto como enciendo las optimizaciones y por lo tanto potencialmente permitirstatic_assert
para ser activado, falla porque no puedo usar argumentos de función en elstatic_assert
. ¿Hay alguna manera de solucionar esto (incluso si eso significa implementar mi propiastatic_assert
)? Siento que mis proyectos de C ++ teóricamente podrían beneficiarse bastante de una declaración de afirmación más inteligente que detecte errores lo antes posible.
No parece hacersmart_assert
Una macro similar a una función resolverá el problema en el caso general. Obviamente lo hará funcionar en este sencillo ejemplo, perocondition
puede provenir de una función a dos niveles del gráfico de llamadas (pero el compilador aún lo conoce como unconstexpr
debido a la inclusión en línea), que se encuentra con el mismo problema de usar un parámetro de función en unstatic_assert
.