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 Teint N. - O construtor deve receber
Testd::integral_constant<int, N>para permitir CTAD. - O método
tamanho()retornaN. - O membro template
imprimiraceita um prefixo de qualquer tipo e imprime os elementos. - O
mainusa CTAD para criar as instâncias e chamaimprimir.
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
- Declaramos
Buffercomtypename Teint N. - O membro
dadosé um array deTcom tamanhoN. - O construtor recebe um valor e um
std::integral_constant<int, N>, que carrega o valor deNno tipo. - O método
tamanho()retornaN. - O membro template
imprimiraceita qualquer tipoUcomo prefixo e imprime os elementos. - Fora da classe, definimos um guia de dedução para que o compilador deduza
TeNa partir dos argumentos do construtor. - No
main, criamosbuf1ebuf2usando CTAD e chamamosimprimir.
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
intem vez destd::integral_constant: o guia não corresponde. - Declarar
imprimircomo 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++