constexpr, static_assert e inlining

Eu já perguntei sobresobrecarga de função com base em se os argumentos sãoconstexpr. Eu estou tentando contornar a resposta decepcionante para essa pergunta para fazer uma função de afirmação mais inteligente. Isso é basicamente o que estou tentando fazer:

<code>inline void smart_assert (bool condition) {
    if (is_constexpr (condition))
        static_assert (condition, "Error!!!");
    else
        assert (condition);
}
</code>

Basicamente, a ideia é que uma checagem em tempo de compilação seja sempre melhor que uma checagem em tempo de execução, se for possível checar em tempo de compilação. No entanto, devido a coisas como inlining e folding constante, eu não posso sempre saber se uma verificação de tempo de compilação é possível. Isso significa que pode haver casos em queassert (condition) compila atéassert(false) e o código está apenas esperando por mim para executá-lo e executar esse caminho antes que eu descubra que há um erro.

Portanto, se houvesse alguma maneira de verificar se a condição é uma constexpr (devido a inlining ou outras otimizações), eu poderia chamarstatic_assert quando possível, e recorrer a uma declaração de tempo de execução de outra forma. Felizmente, o gcc tem o intrínseco__builtin_constant_p (exp), que retorna verdadeiro seexp é um constexpr. Eu não sei se outros compiladores têm algo intrínseco, mas eu esperava que isso resolvesse o meu problema. Este é o código que eu criei:

<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>

ostatic_assert depende do comportamento de curto-circuito deor. E seIS_CONSTEXPR é verdade, entãostatic_assert pode ser usado, e a condição é!true or condition, que é o mesmo que apenascondition. E seIS_CONSTEXPR é falso, entãostatic_assert não pode ser usado, e a condição é!false or condition, o que é o mesmo quetrue e astatic_assert é ignorado. Se ostatic_assert não pode ser verificado porquecondition não é um constexpr, então eu adiciono um tempo de execuçãoassert para o meu código como um último esforço. No entanto, isso não funciona, graças anão ser capaz de usar argumentos de função em umstatic_assert, mesmo que os argumentos sejamconstexpr.

Em particular, isso é o que acontece se eu tentar compilar com o gcc:

<code>// main.cpp
int main () {
    smart_assert (false);
    return 0;
}
</code>

g++ main.cpp -std=c++0x -O0

Tudo está bem, compila normalmente. Não há inlining sem otimização, entãoIS_CONSTEXPR é falso e ostatic_assert é ignorado, então eu só tenho um tempo de execuçãoassert declaração (que falha). Contudo,

<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>

Assim que eu ativar qualquer otimização e, assim, permitir potencialmentestatic_assert para ser acionado, ele falha porque eu não posso usar argumentos de função nostatic_assert. Existe alguma maneira de contornar isso (mesmo que isso signifique implementar meu própriostatic_assert) Eu sinto que meus projetos C ++ poderiam, teoricamente, beneficiar-se bastante de uma declaração de afirmação mais inteligente que detecta erros o mais cedo possível.

Não parece fazersmart_assert uma macro semelhante a uma função resolverá o problema no caso geral. Obviamente, isso fará com que funcione neste exemplo simples, mascondition pode ter vindo de uma função de dois níveis até o gráfico de chamada (mas ainda se torna conhecido para o compilador como umconstexpr devido a inlining), que se depara com o mesmo problema de usar um parâmetro de função em umstatic_assert.

questionAnswers(3)

yourAnswerToTheQuestion