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.

Respuestas a la pregunta(3)

Su respuesta a la pregunta