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:
<code>inline void smart_assert (bool condition) { if (is_constexpr (condition)) static_assert (condition, "Error!!!"); else assert (condition); } </code>
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ó:
<code>#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 </code>
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:
<code>// main.cpp int main () { smart_assert (false); return 0; } </code>
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,
<code>[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 </code>
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
.