Ответ 1
Он явно запрещен в стандарте, даже если некоторые версии VisualStudio разрешают его.
Стандарт С++ 7.1.5.3 Специфичные спецификаторы типов, параграф 2
3.4.4 описывает, как поиск имени продолжается для идентификатора в разработаны типа спецификатор. Если идентификатор разрешает имя класса или имя-имя, специфицированный спецификатор типа вводит он в декларации тот же путь, который вводит простой тип-спецификатор его тип-имя. Если идентификатор разрешается к имени typedef или тип шаблона шаблона, специфицированный тип-спецификатор плохо сформирован. [Примечание: это означает, что, внутри шаблона класса с шаблон типа-параметра T, объявление друга класса 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() {}
};
Это позволит пользователям ошибочно сделать это.
ИЗМЕНИТЬ:
Предстоящий стандарт С++ 11 позволяет вам подружиться с аргументом типа с немного другим синтаксисом:
template <typename T>
class A {
// friend class T; // still incorrect: elaborate type specifier
friend T; // correct: simple specifier, note lack of "class"
};