Desafio C++

Buffer com CTAD e membro template

Enunciado

Implemente uma classe template Buffer que armazena um array de tamanho fixo N do tipo T. A classe deve ter um construtor que preenche todos os elementos com um valor, um método tamanho() que retorna N, e um membro template imprimir que recebe um prefixo de qualquer tipo imprimível e imprime todos os elementos. Use CTAD para criar uma instância de Buffer a partir de um valor e um std::integral_constant<int, N>. No main, crie um Buffer com 4 elementos do tipo double preenchidos com 3.14, e outro com 2 elementos do tipo std::string preenchidos com "C++". Imprima os elementos com prefixos diferentes.

Requisitos

  • A classe deve ter parâmetros typename T e int N.
  • O construtor deve receber T e std::integral_constant<int, N> para permitir CTAD.
  • O método tamanho() retorna N.
  • O membro template imprimir aceita um prefixo de qualquer tipo e imprime os elementos.
  • O main usa CTAD para criar as instâncias e chama imprimir.

Código inicial

#include <iostream>
#include <string>
#include <type_traits> // integral_constant

template <typename T, int N>
class Buffer {
    // TODO
};

// Guia de dedução para CTAD
template <typename T, int N>
Buffer(const T&, std::integral_constant<int, N>) -> Buffer<T, N>;

int main() {
    // Crie buffer1 com 4 doubles preenchidos com 3.14
    // Crie buffer2 com 2 strings preenchidas com "C++"
    // Imprima com prefixos
    return 0;
}

Saída esperada

double: 3.14 3.14 3.14 3.14 
string: C++ C++
Ver dica

No construtor, use um loop para preencher. O guia de dedução permite que o compilador deduza T e N a partir dos argumentos. No main, use std::integral_constant<int, 4>{} como segundo argumento.

Mostrar solução
#include <iostream>
#include <string>
#include <type_traits> // integral_constant

template <typename T, int N>
class Buffer {
    T dados[N];
public:
    // Construtor que recebe valor e integral_constant para dedução
    Buffer(const T& valor, std::integral_constant<int, N>) {
        for (int i = 0; i < N; ++i) dados[i] = valor;
    }

    int tamanho() const { return N; }

    // Membro template: imprime com prefixo de qualquer tipo
    template <typename U>
    void imprimir(U prefixo) const {
        for (int i = 0; i < N; ++i)
            std::cout << prefixo << dados[i] << ' ';
        std::cout << '\n';
    }
};

// Guia de dedução para CTAD
template <typename T, int N>
Buffer(const T&, std::integral_constant<int, N>) -> Buffer<T, N>;

int main() {
    // CTAD: deduz T=double, N=4
    Buffer buf1(3.14, std::integral_constant<int, 4>{});
    buf1.imprimir("double: ");

    // CTAD: deduz T=std::string, N=2
    Buffer buf2(std::string("C++"), std::integral_constant<int, 2>{});
    buf2.imprimir("string: ");

    return 0;
}

Passo a passo

  1. Declaramos Buffer com typename T e int N.
  2. O membro dados é um array de T com tamanho N.
  3. O construtor recebe um valor e um std::integral_constant<int, N>, que carrega o valor de N no tipo.
  4. O método tamanho() retorna N.
  5. O membro template imprimir aceita qualquer tipo U como prefixo e imprime os elementos.
  6. Fora da classe, definimos um guia de dedução para que o compilador deduza T e N a partir dos argumentos do construtor.
  7. No main, criamos buf1 e buf2 usando CTAD e chamamos imprimir.

Por que funciona

O guia de dedução diz ao compilador como deduzir os parâmetros de template a partir dos tipos dos argumentos do construtor. O std::integral_constant<int, N> é um tipo que carrega o valor N em tempo de compilação, permitindo a dedução. O membro template imprimir é independente e pode ser instanciado com qualquer tipo de prefixo.

Erros comuns

  • Esquecer o guia de dedução: CTAD não funciona para parâmetros não-tipo.
  • Passar um int em vez de std::integral_constant: o guia não corresponde.
  • Declarar imprimir como não-template: não aceitaria prefixos de tipos diferentes.

Outra forma de resolver

Usar std::array e uma função livre em vez de membro template. Preferível se não precisar de encapsulamento.

Saída esperada

double: 3.14 3.14 3.14 3.14 
string: C++ C++