Сделать параметр шаблона другом?
Пример:
template class Base { public: Base(); friend class T; };
Теперь это не работает … Есть ли способ сделать это?
Я на самом деле пытаюсь сделать общий герметик classа следующим образом:
- initializer_list и семантика перемещения
- C ++ Получить имя типа в шаблоне
- Выполнение static_assert, что тип шаблона является другим шаблоном
- Почему ключевое слово «typename» необходимо перед квалифицированными зависимыми именами, а не перед квалифицированными независимыми именами?
- Почему C ++ STL настолько сильно зависит от шаблонов? (а не на * интерфейсах *)
class ClassSealer { private: friend class Sealed; ClassSealer() {} }; class Sealed : private virtual ClassSealer { // ... }; class FailsToDerive : public Sealed { // Cannot be instantiated };
Я нашел этот пример на этом сайте, но я не могу его найти … ( здесь )
Я знаю, что есть другие способы сделать это, но сейчас мне интересно, действительно ли вы можете сделать что-то подобное.
- static_assert зависит от параметра шаблона непигового типа (различное поведение на gcc и clang)
- Разница ключевых слов «typename» и «class» в шаблонах?
- Пересылка всех конструкторов в C ++ 0x
- Как объявить шаблонную структуру / class как друга?
- Иерархический идентификатор типа C ++
- Где и почему мне нужно поставить ключевые слова «шаблон» и «имя-тип»?
- Довольно печатные контейнеры STL STL
- Использование заголовка арифметики C ++
Он явно запрещен в стандарте, даже если некоторые версии VisualStudio позволяют это делать.
Стандарт C ++ 7.1.5.3 Специфичные спецификаторы типов, параграф 2
В разделе 3.4.4 описано, как происходит поиск имени для идентификатора в специфицированном спецификаторе типа. Если идентификатор разрешает имя classа или имя-имя, специфицированный спецификатор типа вводит его в объявление так же, как спецификатор простого типа вводит его имя типа. Если идентификатор разрешен для параметра typedef-name или template-type, специфицированный тип-спецификатор плохо сформирован. [Примечание: это подразумевает, что внутри шаблона classа с типом-шаблоном T, class товарищей-друга T ; плохо сформирован. ]
Я признаю код выше как шаблон для печати (запретить расширение) classа. Существует еще одно решение, которое на самом деле не блокирует расширение, но оно будет равномерно отклоняться от classа. Как видно из исходной библиотеки ADOBE :
namespace adobe { namespace implementation { template class final { protected: final() {} }; }} #define ADOBE_FINAL( X ) private virtual adobe::implementation::final
с использованием:
class Sealed : ADOBE_FINAL( Sealed ) {//... };
Хотя он позволяет продлить, если вы действительно его заставляете:
class SealBreaker : public Sealed, ADOBE_FINAL( Sealed ) { public: SealBreaker() : adobe::implementation::final(), Sealed() {} };
Это позволит пользователям ошибочно сделать это.
EDIT :
Предстоящий стандарт C ++ 11 позволяет вам подружиться с аргументом типа с немного другим синтаксисом:
template class A { // friend class T; // still incorrect: elaborate type specifier friend T; // correct: simple specifier, note lack of "class" };
Я нашел простой трюк, чтобы объявить параметры шаблона в качестве друзей:
template < typename T> struct type_wrapper { typedef T type; }; template < typename T> class foo { friend class type_wrapper < T>::type }; // type_wrapper< T>::type == T
Однако я не знаю, как это могло бы помочь определить альтернативную версию герметика classа.
Вам действительно нужно это делать? Если вы хотите, чтобы кто-то не получал ваш class, просто добавьте комментарий и сделайте деструктор не виртуальным.