constexpr e consteval
Parte da seção Programação Orientada a Objetos do Journey de C++ da Coddy. Lição 87 de 104.
C++ permite que os cálculos ocorram em tempo de compilação, em vez de durante a execução, o que pode melhorar significativamente o desempenho. A palavra-chave constexpr (C++11) e a palavra-chave consteval (C++20) dão a você controle sobre quando as expressões são avaliadas.
Uma função constexpr pode ser avaliada em tempo de compilação se receber argumentos constantes, mas também pode ser executada em tempo de execução com inputs não constantes:
#include <iostream>
constexpr int square(int n) {
return n * n;
}
int main() {
constexpr int compileTime = square(5); // Avaliado em tempo de compilação
int x = 7;
int runtime = square(x); // Avaliado em tempo de execução
std::cout << compileTime << "\n"; // 25
std::cout << runtime << "\n"; // 49
}Quando você precisar garantir a avaliação em tempo de compilação, use consteval. Uma função consteval deve produzir uma constante — chamá-la com valores em tempo de execução é um erro de compilação:
consteval int factorial(int n) {
return n <= 1 ? 1 : n * factorial(n - 1);
}
int main() {
constexpr int result = factorial(5); // OK: 120 calculado em tempo de compilação
// int x = 5;
// int bad = factorial(x); // ERROR: x não é uma constante
}Você também pode usar constexpr com variáveis e até mesmo construtores de classes, permitindo que objetos inteiros sejam criados em tempo de compilação. Isso é particularmente útil para tabelas de consulta, valores de configuração ou quaisquer dados que não mudem durante a execução do programa.
Desafio
FácilVocê organizará seu código em três arquivos:
MathUtils.h: defina suas funções matemáticas avaliadas em tempo de compilação.Crie as seguintes funções:
cube: uma funçãoconstexprque recebe uminte retorna seu cubo (n * n * n)triangularNumber: uma funçãoconstexprque calcula o enésimo número triangular usando a fórmula n * (n + 1) / 2. Nesta tarefa, nós a chamamos somente em um contexto de tempo de compilação, armazenando seu resultado em uma variávelconstexpr.sumOfSquares: uma funçãoconstexprque recebe dois inteiros e retorna a soma de seus quadrados (a*a + b*b)
Config.h: crie uma estrutura de configuração usando constantes avaliadas em tempo de compilação.Defina uma struct
Configcom um construtorconstexprque recebe três inteiros:width,heightedepth. Armazene-os como membros públicos. Adicione também um métodoconstexprchamadovolume()que retorna width * height * depth.Abaixo da struct, crie uma constante global
constexprchamadaDEFAULT_CONFIG, inicializada com os valores 10, 20 e 5.main.cpp: leia dois inteiros da entrada representando valores de tempo de execução.Primeiro, demonstre a avaliação em tempo de compilação criando variáveis
constexpr:- Armazene
cube(4)em uma variável constexpr e imprima:Cube of 4: [value] - Armazene
triangularNumber(10)em uma variável constexpr e imprima:10th triangular number: [value] - Imprima o volume da configuração padrão:
Default volume: [value]
Em seguida, demonstre que as funções
constexprtambém podem funcionar em tempo de execução usando seus dois valores de entrada:- Chame
cube()com a primeira entrada e imprima:Cube of [input]: [result] - Chame
sumOfSquares()com ambas as entradas e imprima:Sum of squares: [result]
- Armazene
Por exemplo, com as entradas 3 e 4:
Cube of 4: 64
10th triangular number: 55
Default volume: 1000
Cube of 3: 27
Sum of squares: 25Com as entradas 5 e 12:
Cube of 4: 64
10th triangular number: 55
Default volume: 1000
Cube of 5: 125
Sum of squares: 169Experimente você mesmo
#include <iostream>
#include "MathUtils.h"
#include "Config.h"
using namespace std;
int main() {
// Lê dois inteiros da entrada
int input1, input2;
cin >> input1;
cin >> input2;
// TODO: Demonstra a avaliação em tempo de compilação
// Cria uma variável constexpr armazenando cube(4) e imprime: "Cube of 4: [value]"
// TODO: Create a constexpr variable storing triangularNumber(10)
// and print: "10th triangular number: [value]"
// TODO: Print the default config's volume: "Default volume: [value]"
// TODO: Demonstra o uso em tempo de execução de funções constexpr
// Chama cube() com input1 e imprime: "Cube of [input1]: [result]"
// TODO: Call sumOfSquares() with both inputs
// and print: "Sum of squares: [result]"
return 0;
}
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Programação Orientada a Objetos
1Fundamentos de POO
Arquivos externosBuild e compilação em C++Arquivos de cabeçalho e arquivos-fonteNamespaces e escopoIntrodução à POO em C++Classes vs. objetosO ponteiro 'this'Métodos (funções membro)Atributos (membros de dados)Noções básicas de construtores e destruidoresRevisão - calculadora simples4Propriedades de Classe
Membros de Instância vs. EstáticosGetters e SettersFunções Membro ConstPalavra-chave MutableMétodos e Variáveis EstáticosFunções e Classes FriendRevisão - Gerenciador de Contas Bancárias7Herança
Herança básicaNíveis de acesso da herançaOrdem de chamada de construtor e destrutorSobrescrita de métodosFunções virtuais e VTableHerança múltiplaHerança virtualRevisão - Hierarquia de funcionários10Visão geral da STL
Visão geral e filosofia da STLContêineres da STLIteradoresAlgoritmos da STLFunctors e expressões lambdaRecapitulação - Frequência de palavras13Padrões de Projeto — Parte 1
Introdução aos Padrões de ProjetoPadrão SingletonFactory e Abstract FactoryPadrão BuilderPadrão ObserverPadrão Strategy2Gerenciamento de Memória
Memória Stack vs. HeapPonteiros e ReferênciasMemória Dinâmica (new/delete)Ponteiros Inteligentes em C++RAII em C++Revisão - Gerenciador de Array Dinâmico5Encapsulamento
Especificadores de acesso em C++Especificadores de acesso em profundidadeOcultação de informaçõesStruct vs ClasseClasses aninhadas e internasRecapitulação - Sistema de registros de alunos8Polimorfismo
Polimorfismo em compilação vs. execuçãoSobrecarga de funçõesFunções virtuais revisadasFunções virtuais purasClasses abstratasDesign de interfaces em C++Conversão dinâmica e RTTIRecapitulação — Calculadora de formas11Conceitos Avançados de OOP
Composição vs. HerançaMixins via CRTPIdioma PimplApagamento de TiposClasses Enum e Tipagem ForteTratamento de Exceções em OOPHierarquias de Exceções Personalizadas14Padrões de Projeto — Parte 2
Padrão CommandPadrão AdapterPadrão DecoratorPadrão Template MethodPadrão StatePadrão CompositeRAII como Padrão3Construtores e Destrutores
Construtor PadrãoConstrutor ParametrizadoConstrutor de CópiaConstrutor de MovimentoListas de Inicialização do ConstrutorConstrutores DelegantesAprofundamento em DestrutoresRegra dos Três / Cinco / ZeroRevisão - Classe String6Sobrecarga de Operadores
Introdução à Sobrecarga de OperadoresSobrecarga de Operadores AritméticosSobrecarga de Operadores de ComparaçãoOperadores de FluxoSobrecarga do Operador de AtribuiçãoSobrecarga dos Operadores [] e ()Operadores de Conversão de TipoRecapitulação - Classe Matrix9Templates
Templates de FunçõesTemplates de ClassesEspecialização de TemplatesTemplates VariádicosNoções Básicas de SFINAE e Traits de TiposRecapitulação - Contêiner Genérico12Recursos Modernos do C++
Semântica de Movimentação e RvaluesEncaminhamento PerfeitoExpressões Lambda em Profundidadestd::function e std::bindconstexpr e constevalVinculações Estruturadasoptional, variant, anyPratique por conta própria: Compilador de C++ online