Si el código es inválido ! Esta es una muestra interesante de cómo las plantillas pueden cambiar el significado del código de maneras sutiles. El código siguiente es válida: dice
class List
{
public:
class a {
typedef int type;
friend class b; // that's fine!
};
template <typename U > class b;
};
class b {
List::a::type an_int; // allowed to access private member
};
estándar en 7.3.1.2/3
Si una declaración amigo en una clase que no es local declara por primera vez una clase o function83) la clase de amigo o la función es un miembro del espacio de nombres que lo rodea.
¿Cuándo es una "primera clase declarada"? Dice que también existe
Cuando se busca una declaración previa de una clase o una función declarada como amigo, y cuando el nombre de la clase o función amiga no es ni un nombre calificado ni una plantilla, los ámbitos fuera del alcance del espacio de nombres que lo rodea no se consideran.
La búsqueda de "clase b" se delega de 7.1.5.3/2 a 3.4.4, que a su vez delega en la búsqueda de nombres no calificados en 3.4/7. Toda la pregunta ahora es si el nombre de la plantilla "b" es visible en la clase de declaración de amigo a. Si no es así, el nombre no se encuentra y la declaración de amigo se referirá a una nueva clase declarada en el alcance global. 3.3.6/1 sobre el alcance de la misma dice
El alcance potencial de un nombre declarado en una clase consiste no sólo en la región declarativa siguiente declarador del nombre, sino también de todos los cuerpos de las funciones, los argumentos por defecto, y constructor ctor- inicializadores en esa clase (incluyendo tales cosas en clases anidadas).
Haciendo caso omiso de algunos puntos pedante que harían que esta redacción se aplica a aquí (que eran un defecto sino que están fijados en la versión C++ 0x de ese párrafo, que también hace esto más fácil de leer), esta lista hace no incluir la declaración de amigo como un área donde el nombre de la plantilla es visible.
Sin embargo,, el amigo se declaró en una clase de miembro de una plantilla de clase. Cuando se crea una instancia de la clase de miembro se aplica una búsqueda diferente - ¡la búsqueda de nombres de amigos declarados en una plantilla de clase! El estándar dice
Las clases o funciones de amigo se pueden declarar dentro de una plantilla de clase. Cuando se crea una instancia de una plantilla, los nombres de sus amigos se tratan como si la especialización se hubiera declarado explícitamente en su punto de creación de instancias.
lo tanto, el siguiente código es válido:
template<typename T>
class List
{
public:
class a {
typedef int type;
friend class b; // that's fine!
};
template <typename U > class b;
};
// POI
List<int>::a x;
Cuando eso hace que List<int>::a
a ser implícitamente instanciado, el nombre a
se alzó la vista hacia "// PDI", como si no hubiera habido una especialización explícita declarado. En ese caso, la plantilla List::b
ya ha sido declarada, y esta búsqueda la golpeará y emitirá un error porque es una plantilla y no una clase que no pertenece a la plantilla.
Parece que su análisis es correcto excepto 'El nombre del amigo no se encuentra mediante la búsqueda simple de nombres hasta que se proporciona una declaración coincidente en ese ámbito de espacio de nombres (antes o después de la declaración de clase que otorga amistad)'. Su código no se compila en Comeau, Intel C++ y MSVC++. –
@Prasoon El texto que cita no tiene ningún significado en este caso. El nombre del amigo no se busca aquí (se busca la plantilla). Los compiladores no definen el Estándar, así que no discuto con los compiladores que lo acepten o lo rechacen. Que GCC y Clang acepten que es algo bueno, pero mi respuesta no depende de ellos, sino simplemente del texto estándar que cito. Tanto el frontend EDG (que utilizan Intel y Comeau) como MSVC realmente tienen más errores que este, así que eso no me sorprende). –
Encontré el texto un poco difícil de analizar. Podría haberme perdido algo importante. No importa También eche un vistazo a [esta pregunta similar] (http://stackoverflow.com/questions/4282662/template-friend-a-deadly-combination) y un montón de respuestas. –