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
.