Ambiguidade na desambiguação de herança múltipla
Ao lidar com herança múltipla usando classes base de modelo, surge um problema potencial em relação à resolução de função de membro ambígua. Considere o seguinte cenário:
template
class Base {
public:
template
typename std::enable_if::value>::type foo() {
std::cout Aqui, a função foo() só pode ser chamada quando o parâmetro do modelo corresponde a um dos tipos no pacote Types. Agora, se uma classe derivada herda de múltiplas classes base com conjuntos de tipos não sobrepostos, o compilador pode encontrar ambiguidade ao resolver a chamada foo().
struct Derived: public Base,
public Base
{};
Nesse caso, a chamada Derived().foo() idealmente chamaria a função de membro foo() de Base. No entanto, tanto o GCC quanto o Clang relatam uma ambigüidade.
Por que o compilador não consegue resolver a ambigüidade
O erro de compilação surge devido às regras de mesclagem para pesquisa de função de membro. De acordo com o padrão C, se a função membro não for declarada na própria classe derivada, o processo de pesquisa pesquisará as classes base por sua vez. No entanto, se os conjuntos de declarações nas classes base forem diferentes, a mesclagem se tornará ambígua.
No cenário fornecido, a classe derivada Derived não declara foo() explicitamente, portanto, o compilador deve mesclar os conjuntos de pesquisa do duas classes base. Como as classes base contêm diferentes conjuntos de declarações para foo(), a mesclagem resulta em ambigüidade.
Soluções
Para resolver essa ambigüidade, uma opção é usar declarações using na classe derivada para importar explicitamente as funções de membro desejadas. No entanto, isso exige que o usuário adicione essas declarações, o que pode ser detalhado e impraticável para listas de tipos grandes.
struct Derived: public Base,
public Base
{
using Base::foo;
using Base::foo;
};
Alternativamente, pode-se usar uma classe auxiliar que coleta e mescla as funções-membro de todas as classes base, permitindo que a classe derivada as acesse diretamente.
template
struct BaseCollector : Bases...
{
using Bases::foo...;
};
struct Derived : BaseCollector , Base>
{};
Com essa abordagem, o usuário não precisa adicionar declarações adicionais para resolver a ambiguidade. A classe BaseCollector mescla efetivamente os conjuntos de declarações de todas as classes base, disponibilizando a função foo() para a classe derivada sem ambigüidade.
Isenção de responsabilidade: Todos os recursos fornecidos são parcialmente provenientes da Internet. Se houver qualquer violação de seus direitos autorais ou outros direitos e interesses, explique os motivos detalhados e forneça prova de direitos autorais ou direitos e interesses e envie-a para o e-mail: [email protected]. Nós cuidaremos disso para você o mais rápido possível.
Copyright© 2022 湘ICP备2022001581号-3