Это явно запрещено в стандарте, даже если некоторые версии VisualStudio допускают это.
Стандарт C ++ 7.1.5.3 Разработанные спецификаторы типов, параграф 2
3.4.4 описывает, как происходит поиск имени для идентификатора в
разработаны типа спецификатор. Если
идентификатор разрешается в
имя класса или имя перечисления,
разработанный спецификатор типа вводит
это в декларации то же самое
способ простого спецификатора типа вводит
его тип-имя. Если идентификатор разрешается
к typedef-имени или
тип-параметр шаблона,
разработанный спецификатор типа
плохо сформирован. [Примечание: это означает, что
в шаблоне класса с
шаблон типа-параметра Т,
объявление класс друга T ; является
плохо сформирован. ]
Я распознаю приведенный выше код как шаблон для закрытия (запрета на расширение) класса. Существует еще одно решение, которое не блокирует расширение, но помечает случайное расширение из класса. Как видно из Исходная библиотека ADOBE :
namespace adobe { namespace implementation {
template <class T>
class final
{
protected:
final() {}
};
}}
#define ADOBE_FINAL( X ) private virtual adobe::implementation::final<T>
с использованием:
class Sealed : ADOBE_FINAL( Sealed )
{//...
};
Хотя оно позволяет расширение, если вы действительно его принудительно:
class SealBreaker : public Sealed, ADOBE_FINAL( Sealed )
{
public:
SealBreaker() : adobe::implementation::final<Sealed>(), Sealed() {}
};
Это будет ограничивать пользователей по ошибке сделать это.
РЕДАКТИРОВАТЬ :
Предстоящий стандарт C ++ 11 позволяет вам подружиться с аргументом типа с немного другим синтаксисом:
template <typename T>
class A {
// friend class T; // still incorrect: elaborate type specifier
friend T; // correct: simple specifier, note lack of "class"
};