Menu
Coddy logo textTech

Templates Variádicos

Parte da seção Programação Orientada a Objetos do Journey de C++ da Coddy. Lição 67 de 104.

E se você precisar de uma função que aceite qualquer número de argumentos de quaisquer tipos? Os templates tradicionais exigem que você especifique exatamente quantos parâmetros de tipo são necessários. Templates variádicos resolvem isso permitindo que os templates aceitem um número arbitrário de argumentos de template.

A sintaxe usa ... (reticências) para criar um pacote de parâmetros:

template <typename... Args>
void printAll(Args... args) {
    // Args é um pacote de parâmetros de template
    // args é um pacote de parâmetros de função
}

Para processar os argumentos, normalmente você usa recursão com um caso-base. O pacote de parâmetros se expande um argumento por vez até que nenhum reste:

// Caso base: nenhum argumento restante
void print() {
    std::cout << std::endl;
}

// Caso recursivo: processa o primeiro argumento, recursa com o restante
template <typename T, typename... Rest>
void print(T first, Rest... rest) {
    std::cout << first << " ";
    print(rest...);  // Expande os argumentos restantes
}

print(1, 3.14, "hello", 'x');  // Saída: 1 3.14 hello x

Você também pode usar expressões de fold (C++17) para operações mais simples sem recursão explícita:

template <typename... Args>
auto sum(Args... args) {
    return (args + ...);  // Expressão fold: adiciona todos os argumentos
}

std::cout << sum(1, 2, 3, 4) << std::endl;  // Saída: 10

Os templates variádicos viabilizam muitos recursos da biblioteca padrão, como std::make_unique, std::tuple e std::function. Eles permitem funções com segurança de tipos que funcionam com qualquer combinação de tipos e quantidades de argumentos.

challenge icon

Desafio

Fácil

Vamos criar um sistema de registro flexível que usa templates variádicos para lidar com mensagens com qualquer número de argumentos. Você criará utilitários que podem concatenar valores, contar argumentos e imprimir uma saída formatada — tudo usando pacotes de parâmetros.

Você organizará seu código em dois arquivos:

  • Variadic.h: defina suas funções de template variádicas aqui.

    Crie uma função printAll que imprima todos os seus argumentos separados por espaços, seguidos por uma nova linha. Use a abordagem recursiva com um caso-base que imprime apenas uma nova linha e um caso recursivo que imprime o primeiro argumento, um espaço e, em seguida, faz a recursão com os argumentos restantes.

    Crie uma função countArgs que retorne o número de argumentos passados a ela. Use sizeof... para obter o tamanho do pacote de parâmetros.

    Crie uma função sum que some todos os argumentos numéricos e retorne o resultado. Use uma expressão de dobra com o operador +.

    Crie uma função product que multiplique todos os argumentos numéricos e retorne o resultado. Use uma expressão de dobra com o operador *.

  • main.cpp: leia quatro entradas, cada uma em uma linha separada:
    1. Um inteiro
    2. Um double
    3. Uma string
    4. Um caractere

    Demonstre seus templates variádicos:

    1. Chamando printAll com as quatro entradas e imprimindo o resultado
    2. Imprimindo a contagem de argumentos ao chamar countArgs com o inteiro, o double e o caractere: Argument count: <count>
    3. Calculando a soma do inteiro, do double e dos valores 10 e 5 e, em seguida, imprimindo: Sum: <result>
    4. Calculando o produto do inteiro e dos valores 2 e 3 e, em seguida, imprimindo: Product: <result>
    5. Chamando printAll apenas com a string (um único argumento)
    6. Chamando printAll sem argumentos (deve imprimir apenas uma nova linha)

Por exemplo, com as entradas 5, 2.5, Hello e X:

5 2.5 Hello X 
Argument count: 3
Sum: 22.5
Product: 30
Hello 

Observe como printAll lida com qualquer número de argumentos de tipos mistos, de quatro argumentos até zero. As funções sum e product usam expressões de dobra para combinar todos os valores de forma elegante, sem recursão explícita. Sua função countArgs demonstra como sizeof... fornece o tamanho do pacote em tempo de compilação.

Experimente você mesmo

#include <iostream>
#include <string>
#include "Variadic.h"

using namespace std;

int main() {
    // Ler entradas
    int intVal;
    double doubleVal;
    string strVal;
    char charVal;
    
    cin >> intVal;
    cin >> doubleVal;
    cin >> strVal;
    cin >> charVal;
    
    // TODO: Chamar printAll com todas as quatro entradas
    
    // TODO: Print argument count using countArgs with intVal, doubleVal, and charVal
    // Format: "Argument count: <count>"
    
    // TODO: Calcular e imprimir a soma de intVal, doubleVal, 10 e 5
    // Formato: "Sum: <result>"
    
    // TODO: Calcular e imprimir o produto de intVal, 2 e 3
    // Formato: "Product: <result>"
    
    // TODO: Chamar printAll apenas com a string
    
    // TODO: Chamar printAll sem argumentos
    
    return 0;
}
quiz iconTeste seus conhecimentos

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

Pratique por conta própria: Compilador de C++ online