OPENEDU Seu Conhecimento Cresce a Cada Questão Resolvida

Doadores E Receptores Universais

Doadores E Receptores Universais

O que são doadores e receptores universais

São funções ou métodos escritos de forma que aceitam qualquer tipo de dado sem precisar de especialização para cada caso. No C++, você faz isso com templates. Na prática, isso quer dizer que um vetor genérico, por exemplo, funciona com int, float, std::string ou uma struct que você criou hoje de manhã, sem reescrever nada. Um doador universal é a função que recebe qualquer coisa como parâmetro. Um receptor universal é a função que devolve qualquer coisa. O template resolve os dois lados da moeda.

Como implementar doadores e receptores universais em C++

Vou mostrar o padrão mais usado, que é o template de função e o template de classe. Para um doador universal simples: template<typename T>
void receber_qualquer_coisa(T valor) {
  // faz algo com valor
}

Chamar passando int, double ou seu próprio objeto funciona da mesma forma. O compilador gera a versão certa automaticamente. Para o receptor universal, o truque é usar template em conjunto com return type deduction, que existe desde o C++14: template<typename T>
T criar_valor() {
  return T{};
}

Conheça a Tabela de Compatibilidade dos Doadores e dos Receptores. 🇸🇹 ...
Conheça a Tabela de Compatibilidade dos Doadores e dos Receptores. 🇸🇹 ...

Assim você pede um double, um int, uma std::vector — tudo funciona.

Quando isso dá problema

A parte que ninguém conta é que template genérico não significa ilimitado. Se sua função usa operadores que não existem em todos os tipos, o compilador trava na compilação. Já perdi duas horas tentando debugar um erro de "no match for operator<

" quando na verdade o problema era que o tipo passado não tinha stream de saída definido. O erro aparecia em uma linha inteira no topo do stack, mas a causa estava em uma chamada que parecia inofensiva. O workaround que uso hoje é adicionar constraints com concepts (C++20). Fica assim: template<std::integral T>
void fazer_algo(T valor) {
  // só aceita inteiros
}

Isso elimina aambiguidade e o erro de compilação mostra exatamente qual constraint falhou. Antes eu usava SFINAE com std::enable_if, que funcionava mas gerava mensagens de erro quase ilegíveis.

Luke Abbate Receptores De Doadores VIGARELLO, História Das Práticas
Luke Abbate Receptores De Doadores VIGARELLO, História Das Práticas

Limitações reais

Doadores e receptores universais não resolvem tudo. Eles geram código duplicado por tipo — se você passa int e double, o compilador gera duas versões da função. Isso aumenta o tamanho do binário. Em projetos com templates pesados, o tempo de compilação pode triplicar comparado a uma função especializada. Também existe o problema de polimorfismo. Templates resolvem polimorfismo em tempo de compilação. Se você precisa decidir em tempo de execução qual tipo tratar, herança com classes base e ponteiros para base ainda é o caminho mais prático. Para bibliotecas externas sem acesso ao código-fonte, o template não funciona tão bem. É mais fácil usar void* combinado com casting controlado, ainda que isso abra mão da segurança de tipos.

Dica prática sobre especialização

A coisa mais importante que aprendi é que sempre deve haver uma especialização total ou parcial para tipos problemáticos. Um vetor genérico que funciona para tipos trivialmente copiáveis pode travar com std::unique_ptr porque esse tipo não é copiável, apenas movível. A solução foi especializar o construtor de cópia para esses casos e usar std::move internamente. Demorou um dia inteiro para identificar, porque o erro só aparecia em certas arquiteturas devido a alinhamento de memória diferente. Se você está começando com doadores e receptores universais, comece com functions template simples antes de partir para classes template. A curva de aprendizado é menor e os erros são mais fáceis de rastrear. A maioria dos bugs que vejo em código de produção vem de templates aninhados demais, onde ninguém sabe mais qual instância está sendo usada em cada ponto da chamada.

Vetores de Esquema De Transfusão De Tipos Sanguíneos De Receptores E ...
Vetores de Esquema De Transfusão De Tipos Sanguíneos De Receptores E ...