Estou tentando calcular o comprimento de uma string literal em tempo de compilação. Para fazer isso, estou usando o seguinte código:
#include <cstdio>
int constexpr length(const char* str)
{
return *str ? 1 + length(str + 1) : 0;
}
int main()
{
printf("%d %d", length("abcd"), length("abcdefgh"));
}
Tudo funciona conforme o esperado, o programa imprime 4 e 8. O código de montagem gerado pelo clang mostra que os resultados são calculados em tempo de compilação:
0x100000f5e: leaq 0x35(%rip), %rdi ; "%d %d"
0x100000f65: movl $0x4, %esi
0x100000f6a: movl $0x8, %edx
0x100000f6f: xorl %eax, %eax
0x100000f71: callq 0x100000f7a ; symbol stub for: printf
Minha pergunta: é garantido pelo padrão que a length
função será avaliada em tempo de compilação?
Se isso for verdade, a porta para cálculos de literais de string em tempo de compilação acabou de se abrir para mim ... por exemplo, posso calcular hashes em tempo de compilação e muito mais ...
<cstdio>
e, em seguida, a chamada::printf
não é portátil. O padrão exige apenas<cstdio>
fornecerstd::printf
.printf
pode levar a muito menos código para lidar.Respostas:
Expressões constantes não são garantidas para serem avaliadas em tempo de compilação, nós temos apenas uma citação não normativa do rascunho da seção padrão C ++
5.19
Expressões constantes que diz o seguinte:Você pode atribuir o resultado à
constexpr
variável para ter certeza de que ele é avaliado em tempo de compilação, podemos ver isso na referência C ++ 11 de Bjarne Stroustrup que diz ( grifo meu ):Por exemplo:
Bjarne Stroustrup fornece um resumo de quando podemos garantir a avaliação do tempo de compilação nesta entrada do blog isocpp e diz:
Portanto, isso descreve dois casos em que deve ser avaliado em tempo de compilação:
shall be ... converted constant expression
oushall be ... constant expression
é usada, como um limite de matriz.constexpr
conforme delineado acima.fonte
constexpr int x = 5;
, observe que ele não requer o valor em tempo de compilação (assumindo que não seja usado como um parâmetro de modelo ou outros enfeites) e realmente emitir código que calcula o valor inicial em tempo de execução usando 5 valores imediatos de 1 e 4 ops de adição. Um exemplo mais realista: o compilador pode atingir um limite de recursão e adiar a computação até o tempo de execução. A menos que você faça algo que force o compilador a realmente usar o valor, "garantia de avaliação em tempo de compilação" é um problema de QOI.constexpr
cálculo do mal absoluto. É até mesmo gratuito esperar 1 segundo por personagem em uma determinada linha de origem, ou pegar uma determinada linha de origem e usá-la para semear uma posição de xadrez e, em seguida, jogar os dois lados para determinar quem ganhou.É realmente fácil descobrir se uma chamada para uma
constexpr
função resulta em uma expressão constante central ou se está apenas sendo otimizada:Use-o em um contexto onde uma expressão constante é necessária.
fonte
-pedantic
, se você usar gcc. Caso contrário, você não receberá avisos e errosenum { Whatever = length("str") }
?static_assert(length("str") == 3, "");
constexpr auto test = /*...*/;
é provavelmente o mais geral e direto.Apenas uma observação, que compiladores modernos (como gcc-4.x) fazem
strlen
para literais de string em tempo de compilação porque normalmente é definido como uma função intrínseca . Sem otimizações habilitadas. Embora o resultado não seja uma constante de tempo de compilação.Por exemplo:
Resulta em:
fonte
strlen
é uma função incorporada, se a usarmos-fno-builtins
volta a chamá-la em tempo de execução, veja-a ao vivostrlen
éconstexpr
para mim, mesmo com-fno-nonansi-builtins
(parece-fno-builtins
que não existe mais no g ++). Eu digo "constexpr", porque posso fazer issotemplate<int> void foo();
efoo<strlen("hi")>();
g ++ - 4.8.4Deixe-me propor outra função que calcula o comprimento de uma string em tempo de compilação sem ser recursiva.
Dê uma olhada neste código de amostra em ideone .
fonte
char temp[256]; sprintf(temp, "%u", 2); if(1 != length(temp)) printf("Your solution doesn't work");
ideone.com/IfKUHVNão há garantia de que uma
constexpr
função seja avaliada em tempo de compilação, embora qualquer compilador razoável o faça nos níveis de otimização apropriados habilitados. Por outro lado, os parâmetros do template devem ser avaliados em tempo de compilação.Usei o seguinte truque para forçar a avaliação em tempo de compilação. Infelizmente, ele só funciona com valores integrais (ou seja, não com valores de ponto flutuante).
Agora, se você escrever
você pode ter certeza de que a
if
instrução é uma constante de tempo de compilação sem sobrecarga de tempo de execução.fonte
len
serconstexpr
meiolength
deve ser avaliado em tempo de compilação de qualquer maneira.if
condição (em que era essencial que o compilador eliminasse o código morto) para a qual eu originalmente usei o truque.Uma breve explicação da entrada da Wikipedia sobre Expressões constantes generalizadas :
Ter a
constexpr
palavra - chave antes de uma definição de função instrui o compilador a verificar se essas limitações são atendidas. Se sim, e a função é chamada com uma constante, o valor retornado é garantido como constante e, portanto, pode ser usado em qualquer lugar em que uma expressão constante seja necessária.fonte