MSVC, Clang y GCC no están de acuerdo con este código:
struct Base { int x; };
struct Der1 : public Base {};
struct Der2 : public Base {};
struct AllDer : public Der1, public Der2 {
void foo() {
Der1::Base::x = 5;
}
};
CCG:
<source>: In member function 'void AllDer::foo()':
<source>:10:21: error: 'Base' is an ambiguous base of 'AllDer'
10 | Der1::Base::x = 5;
| ^
Compiler returned: 1
Clang da un error similar y MSVC no da ningún error.
¿Quién está aquí?
Supongo que esto está cubierto en [class.member.lookup] , pero tengo dificultades para entender lo que está tratando de decirme para este caso. Por favor, cite las partes relevantes y, si es posible, explique en inglés simple
PD: Inspirado por esta pregunta ¿Por qué la referencia a la clase base es ambigua con :: -operator a través de la clase derivada?
PPS: En realidad, mi duda es si se Der1::Baserefiere al tipo, que sería Base(y luego Der2::Basees exactamente el mismo tipo), o al subobjeto. Estoy convencido de que es el primero, pero si es el último, entonces MSVC estaría en lo cierto.
c++
language-lawyer
multiple-inheritance
diamond-problem
qualified-name
idclev 463035818
fuente
fuente

::Base, pero la pregunta real parece ser ligeramente diferente aquí. Hay dos subobjetos de tipoBase, y ambos tienen unBase::xmiembro.Respuestas:
Para responder la pregunta en el título, sí, hace
Derived1::Basereferencia al nombre de la clase inyectada [class.pre]Basey también lo haceDerived2::Base. Ambos se refieren a la clase.::Base.Ahora, si
Basetuviera un miembro estáticox, entonces la búsqueda deBase::xsería inequívoca. Sólo hay uno.El problema en este ejemplo es que
xes un miembro no estático yAllDertiene dos de esos miembros. Puede desambiguar dicho accesoxespecificando una clase base inequívoca de laAllDercual solo tiene unxmiembro.Derived1es una clase base inequívoca y tiene unxmiembro, por loDerived1::xque especifica inequívocamente a cuál de los dosxmiembrosAllDerse refiere.Basetambién tiene un soloxmiembro, pero no es una base inequívoca deAllDer. Cada instancia deAllDertiene dos subobjetos de tipoBase. PorBase::xlo tanto, es ambiguo en su ejemplo. Y dado queDerived1::Basees solo otro nombre paraBase, esto sigue siendo ambiguo.[class.member.lookup] especifica que
xse busca en el contexto del especificador de nombre anidado, por lo que debe resolverse primero. De hecho, estamos buscandoBase::x, noDerived1::x, porque comenzamos resolviendoDerived1::BasecomoBase. Esta parte tiene éxito, solo hay unaxen laBase.Nota 12 en [class.member.lookup] que le dice explícitamente que el uso de una búsqueda de nombres inequívoca aún puede fallar cuando hay múltiples subobjetos con ese mismo nombre.D::ien ese ejemplo es básicamente tuBase::x.fuente
template <typname A,typename B> struct foo : A,Bcódigo inventado para acceder a miembros de una base deAyB. En tal caso, quiero obtener un errorLa razón por la que puede referirse al nombre de la clase como miembro de la clase es porque cpp lo alias para un uso conveniente, como si escribiera
using Base = ::Base;dentro de Base.El problema que enfrenta es que
Der1::BaseesBase.Por lo tanto, cuando escribes
Der1::Base::x, es lo mismo queBase::x.fuente
usingestá escrita en el estándar, y creo que esa es la clave para interpretar lo que dice la expresión.cl /c /Wall /WX /Od /MDd /Za /permissive- /std:c++17 main.cppcomo línea de comando, obtengomain.cpp(7): error C2597: illegal reference to non-static member 'A::x'