Está explícitamente prohibido en el estándar, incluso si algunas versiones de VisualStudio lo permiten.
C++ estándar 7.1.5.3 elaborados especificadores de tipo, párrafo 2
3.4.4 describes how name lookup proceeds for the identifier in an elaborated-type-specifier. If the identifier resolves to a class-name or enum-name, the elaborated-type-specifier introduces it into the declaration the same way a simple-type-specifier introduces its type-name. If the identifier resolves to a typedef-name or a template type-parameter, the elaborated-type-specifier is ill-formed. [Note: this implies that, within a class template with a template type-parameter T, the declaration friend class T; is ill-formed. ]
I reconocen el código de seguridad como un patrón para sellar (no permitir la extensión de) una clase. Hay otra solución, que realmente no bloquea la extensión, pero que indicará que se extiende de forma inadvertida desde la clase. Como se ve en ADOBE Source Library:
namespace adobe { namespace implementation {
template <class T>
class final
{
protected:
final() {}
};
}}
#define ADOBE_FINAL(X) private virtual adobe::implementation::final<T>
con el uso:
class Sealed : ADOBE_FINAL(Sealed)
{//...
};
Mientras que permite la extensión si realmente lo fuerza:
class SealBreaker : public Sealed, ADOBE_FINAL(Sealed)
{
public:
SealBreaker() : adobe::implementation::final<Sealed>(), Sealed() {}
};
Será evitar que los usuarios por error hacerlo.
EDITAR:
El novedoso estándar de C++ 11 no le permiten hacerse amigo de un argumento de tipo con una sintaxis ligeramente diferente:
template <typename T>
class A {
// friend class T; // still incorrect: elaborate type specifier
friend T; // correct: simple specifier, note lack of "class"
};
... una vez más, C++ 11 permite la palabra clave "final", por ejemplo: clase X final {...} (o puede hacer funciones virtuales individuales finales). En cualquier caso, probé el código anterior ("amigo T") con g ++ 4.8.4 _without_ the -std = C++ 11 y compila bien. –