c++ - El nombre de clase inyectado ambiguo no es un error
multiple-inheritance language-lawyer (2)
¡Lo encontré! ¡Está justo ahí en el estándar! ¡Yo tenía razón! ¡ Debería ser ambiguo!
Cláusula 14.6.1 Párrafo
Una búsqueda que encuentra un nombre de clase inyectada (10.2) puede resultar en una ambigüedad en ciertos casos (por ejemplo, si se encuentra en más de una clase base). Si todos los nombres de clase inyectados que se encuentran se refieren a especializaciones de la misma plantilla de clase, y si el nombre va seguido de una lista de argumentos de plantilla, la referencia se refiere a la propia plantilla de clase y no a una especialización de la misma, y no es ambiguo [Ejemplo:
template <class T> struct Base { };
template <class T> struct Derived: Base<int>, Base<char>
{
typename Derived::Base b; // error: ambiguous typename
Derived::Base<double> d; // OK
};
—En ejemplo]
En pocas palabras: este es otro error de compilación de Microsoft . Deshabilitar las extensiones de idioma tampoco ayuda.
Lo que leí en el estándar de C ++ sobre los nombres de clase inyectados contradice (como lo veo) con el comportamiento de un programa de ejemplo que presentaré en breve. Esto es lo que leí:
A partir del 3.4 (apartado 3)
El nombre de clase inyectada de una clase (cláusula 9) también se considera un miembro de esa clase a los efectos de ocultar y buscar nombre.
A partir del 9 (apartado 2)
Se inserta un nombre de clase en el ámbito en el que se declara inmediatamente después de ver el nombre de clase. El nombre de la clase también se inserta en el alcance de la clase en sí; Esto se conoce como el nombre de clase inyectado. Para propósitos de verificación de acceso, el nombre de clase inyectada se trata como si fuera un nombre de miembro público.
De estos entiendo que lo siguiente es una unidad de traducción bien formada y se compila con éxito.
#include <vector>
class X: std::vector<int>
{
vector mem;
};
Sin embargo, supongo que lo siguiente debería haber producido un error, pero no lo hace
#include <vector>
class X: std::vector<int>, std::vector<char>
{
vector mem; //compiles OK... mem is apparently std::vector<int>
};
Como el vector
nombre se inyecta tanto en std::vector<int>
como en std::vector<char>
como si fuera un nombre de miembro público, X debería heredarlo, y por lo tanto el vector
nombre en X
debería ser ambiguo. ¿Me estoy perdiendo de algo?
PS estoy usando MSVC9.0
No, no te estás perdiendo nada, y tu compilador parece comportarse con errores. Puede ver cómo gcc lo maneja aquí: http://ideone.com/MI9gz
Su mensaje de error es:
prog.cpp:4:4: error: reference to ''vector'' is ambiguous
/usr/lib/gcc/i686-pc-linux-gnu/4.5.1/../../../../include/c++/4.5.1/bits/stl_vector.h:171:5: error: candidates are: class std::vector<char> std::vector<char>::vector
/usr/lib/gcc/i686-pc-linux-gnu/4.5.1/../../../../include/c++/4.5.1/bits/stl_vector.h:171:5: error: class std::vector<int> std::vector<int>::vector