Impulsojunte-se à Impulso

17/11/23

7 min de leitura

Os benefícios de usar a asserção estática em C++

Karine BallardinKarine Ballardin

Na maioria das linguagens de programação, uma asserção é frequentemente utilizada para detectar estados e situações inesperados ou não intencionais de um programa. Entretanto, uma asserção também é uma verificação condicional em tempo de execução. Isso significa que devs precisam executar esse trecho específico de código para que a asserção tenha efeito.

Mas como isso pode ajudar devs? Um novo recurso a partir do C++11 é o static_assert , uma versão em tempo de compilação do assert() , que verifica as condições em tempo de compilação. Além disso, interrompe a compilação se a condição não for atendida. Inclusive, esse tipo de assert é muito mais útil para impor restrições às práticas de desenvolvimento em um projeto C++. Afinal, não requer um teste de tempo de execução para verificar o assert. Portanto, vamos dar uma olhada nos benefícios do uso desta asserção estática dentro dessa linguagem versátil.

Sintaxe

O static_assert pode ser usado no escopo do tipo, no escopo global ou no escopo funcional. Abaixo estão exemplos do escopo do tipo e do escopo funcional.

O segundo parâmetro, a string de mensagem, é obrigatório no C++11, mas torna-se opcional no C++17. Quando compilado ou executado no clang, o compilador apresentará um erro com uma mensagem semelhante à seguinte:

Uma diferença importante entre static_assert e assert() regular é que o primeiro exige que a expressão da condição seja uma constante integral. Mas o que isso significa? Como uma condição está sendo afirmada em tempo de compilação, qualquer condição desse tipo também pode ser avaliada como um número inteiro em tempo de compilação. No exemplo acima, 2 == 3 pode ser avaliado em tempo de compilação. E a maneira mais fácil de testar se algo pode ser uma constante integral é se a declaração de tipo do objeto de destino pode ter constexpr. Um exemplo comum é o uso de um tipo de mapa que atua como um guia “constante”.

O TESTMAP acima é estático e constante, o que compila bem, mas pode haver um problema se for alterado para:

Portanto, tipos std:: como mapas não podem ser usados com static_assert . Isso também se aplica aos casos em que os tipos std:: são usados em modelos, como abaixo.

Isso não será compilado porque checkIfContains, apesar de estar marcado como constexpr, usa iteradores no contexto da classe std::vector que não estão marcados como constexpr.

No entanto, isso não é uma coisa necessariamente ruim, e ainda há maneiras poderosas de usar static_assert.

Funções

A primeira maneira significativa de utilizar static_assert é por meio de funções. Se uma função puder ser marcada como constexpr , ela poderá ser usada no contexto de um static_assert:

No exemplo acima, uma instrução switch é usada para verificar um parâmetro inteiro. O tipo de retorno da função é constexpr bool. Não há problema em avaliar em tempo de compilação porque nada é um tipo não literal ou dependente de estados de tempo de execução. Além disso, você também pode usar funções que tenham variáveis locais e operem sobre elas.

Inclusive, vale dizer que o uso de funções também pode ser mais complexo. Alguns tipos std:: satisfazem os requisitos para funcionar em um static_assert , como std::array.

As funções também podem realizar verificações de tipos em vez de valores integrais. O cabeçalho a partir do C++11 oferece vários modelos diferentes para verificar atributos específicos ou condições de tipos. Um exemplo é std::is_same<a, b=””>(), que verifica se os dois tipos são o mesmo.

Isso pode ser combinado com uma função de modelo para fazer verificações em tempo de compilação em relação a um tipo:

Escopos

Também é possível restringir o static_assert a um escopo de classe ou escopo de função. A vantagem disso é que você pode controlar com mais precisão o ponto em que o static_assert será verificado.

Esse modelo garantirá que a afirmação seja avaliada somente no escopo em que ensure_registered_type for construído. Em vez de apenas aplicar a asserção a um determinado arquivo ou ponto de compilação em um projeto, essa abordagem pode ser usada para aplicar a asserção em vários pontos diferentes, como em main():

Este exemplo usa o decyltype para decifrar um tipo de variável e construir o modelo ensure_registered_type com esse tipo.

Quer entender mais desse tipo de programação?

Então você precisa participar da nossa Comunidade no Discord. Temos vários e várias devs por lá, das mais diferentes stacks. Ou seja, é o lugar perfeito para um intercâmbio de informações e experiências profissionais. Além disso, temos vagas de trabalho por lá, eventos exclusivos, aulas gratuitas de inglês e cupons de desconto. E sempre que você tiver alguma dúvida, pode me acionar lá pelo @ine. Estou te esperando, hein? Para participar é só clicar aqui.

E olha, também estamos no WhatsApp, viu? Se você preferir, pode ir trocar uma ideia com devs por lá.

[Este texto foi inspirado e traduzido a partir deste artigo do Medium]

Nós usamos cookies para melhorar sua experiência no site. Ao aceitar, você concorda com nossa Política de Privacidade

Assine nossa newsletter

Toda semana uma News com oportunidades de trabalho, conteúdos selecionados, eventos importantes e novidades sobre o Mundo da Tecnologia.

Pronto, em breve você vai receber novidades 👍