Ambigüedad al desambiguar la herencia múltiple
Cuando se trata de herencia múltiple usando clases base de plantilla, surge un problema potencial con respecto a la resolución ambigua de funciones miembro. Considere el siguiente escenario:
template
class Base {
public:
template
typename std::enable_if::value>::type foo() {
std::cout Aquí, la función foo() solo se puede llamar cuando el parámetro de la plantilla coincide con uno de los tipos en el paquete Tipos. Ahora, si una clase derivada hereda de múltiples clases base con conjuntos de tipos que no se superponen, el compilador puede encontrar ambigüedad al resolver la llamada foo().
struct Derived: public Base,
public Base
{};
En este caso, la llamada Derived().foo() idealmente llamaría a la función miembro foo() desde Base. Sin embargo, tanto GCC como Clang informan una ambigüedad.
Por qué el compilador no puede resolver la ambigüedad
El error de compilación surge debido a las reglas de combinación para la búsqueda de funciones miembro. Según el estándar C, si la función miembro no está declarada en la propia clase derivada, el proceso de búsqueda busca a su vez en las clases base. Sin embargo, si los conjuntos de declaración en las clases base difieren, la combinación se vuelve ambigua.
En el escenario dado, la clase derivada Derived no declara foo() explícitamente, por lo que el compilador debe fusionar los conjuntos de búsqueda de las clases base. dos clases base. Dado que las clases base contienen diferentes conjuntos de declaraciones para foo(), la combinación genera ambigüedad.
Soluciones
Para resolver esta ambigüedad, una opción es utilizar declaraciones en la clase derivada para importar explícitamente las funciones miembro deseadas. Sin embargo, esto requiere que el usuario agregue estas declaraciones, que pueden ser detalladas y poco prácticas para listas de tipos grandes.
struct Derived: public Base,
public Base
{
using Base::foo;
using Base::foo;
};
Como alternativa, se puede utilizar una clase auxiliar que recopile y combine las funciones miembro de todas las clases base, permitiendo que la clase derivada acceda a ellas directamente.
template
struct BaseCollector : Bases...
{
using Bases::foo...;
};
struct Derived : BaseCollector , Base>
{};
Con este enfoque, el usuario no necesita agregar ninguna declaración adicional para resolver la ambigüedad. La clase BaseCollector fusiona efectivamente los conjuntos de declaraciones de todas las clases base, haciendo que la función foo() esté disponible para la clase derivada sin ambigüedad.
Descargo de responsabilidad: Todos los recursos proporcionados provienen en parte de Internet. Si existe alguna infracción de sus derechos de autor u otros derechos e intereses, explique los motivos detallados y proporcione pruebas de los derechos de autor o derechos e intereses y luego envíelos al correo electrónico: [email protected]. Lo manejaremos por usted lo antes posible.
Copyright© 2022 湘ICP备2022001581号-3