💻 Exemplos: Capítulo 13: Templates Modernos, Cláusula Requires e C++20 Concepts
💻 Exemplos: Capítulo 13: Templates Modernos, Cláusula Requires e C++20 Concepts
Especialização em Sistemas com C++ • Demonstrações Práticas Compiláveis
🎯 Objetivo dos Exemplos
Apresentar a programação genérica moderna com restrições formais de tipos em tempo de compilação: declaração de concept, restrições com a cláusula requires, eliminação de erros crípticos de template (SFINAE / template error dumps) e criação de funções genéricas altamente expressivas e otimizadas sem custo de runtime.
1. Código Fonte Completo (main.cpp)
/**
* @file main.cpp
* @brief Metaprogramação genérica moderna com C++20 Concepts e cláusula requires.
*/
#include <iostream>
#include <concepts>
#include <string>
#include <vector>
// 1. Definição de Concepts Personalizados no C++20
// Concept que exige que o tipo seja numérico (integral ou ponto flutuante)
template <typename T>
concept Numerico = std::integral<T> || std::floating_point<T>;
// Concept que exige que o tipo possua método serialize() retornando std::string
template <typename T>
concept Serializavel = requires(T a) {
{ a.serialize() } -> std::same_as<std::string>;
};
// 2. Função com Restrição de Concept (Sintaxe Direta de Parâmetro)
template <Numerico T>
T calcular_potencia_sinal(T amplitude, T ganho) {
return amplitude * ganho;
}
// 3. Função com Cláusula requires Adicional
template <typename T>
requires Serializavel<T>
void persistir_telemetria(const T& registro) {
std::cout << "[Storage] Gravando payload serializado: " << registro.serialize() << '\n';
}
// Estruturas de Teste
struct SensorLog {
int id;
double temperatura;
std::string serialize() const {
return "SensorLog{id=" + std::to_string(id) +
", temp=" + std::to_string(temperatura) + "}";
}
};
int main() {
std::cout << "=== CAPÍTULO 13: TEMPLATES E C++20 CONCEPTS ===" << '\n';
// 4. Invocação de função restrita a tipos numéricos
auto pot_inteira = calcular_potencia_sinal(10, 5);
auto pot_real = calcular_potencia_sinal(3.5, 2.0);
std::cout << "Potencia Inteira: " << pot_inteira << " W" << '\n';
std::cout << "Potencia Real: " << pot_real << " W" << '\n';
// Se tentássemos: calcular_potencia_sinal("erro", "str");
// O compilador rejeitaria com mensagem amigável: 'constraints not satisfied'!
// 5. Invocação de função com Concept Serializavel
SensorLog log_temperatura{ 402, 78.4 };
persistir_telemetria(log_temperatura);
// 6. Restrição Ad-Hoc com requires em Função Lambda (C++20)
auto formatador_hex = [](std::integral auto valor) {
std::cout << "Valor Hex: 0x" << std::hex << valor << std::dec << '\n';
};
formatador_hex(255);
formatador_hex(65535LL);
return 0;
}
2. Instruções de Compilação e Execução
# Compilação com GCC / Clang
g++ -std=c++20 -Wall -Wextra -O2 main.cpp -o app_concepts
./app_concepts
# Compilação com MSVC
cl /std:c++20 /EHsc /W4 /O2 main.cpp /Fe:app_concepts.exe
.\app_concepts.exe
3. Saída Esperada no Terminal
=== CAPÍTULO 13: TEMPLATES E C++20 CONCEPTS ===
Potencia Inteira: 50 W
Potencia Real: 7 W
[Storage] Gravando payload serializado: SensorLog{id=402, temp=78.400000}
Valor Hex: 0xff
Valor Hex: 0xffff