Подтвердить что ты не робот

Почему я не могу объявить друга через typedef?

Кто-нибудь знает, почему typedefs имен классов не работают, как имена классов для объявления друга?

class A
{
public:
};

class B : public A
{
public:
   typedef A SUPERCLASS;
};

typedef A X;

class C
{
public:
   friend class A;             // OK
   friend class X;             // fails
   friend class B::SUPERCLASS; // fails
};
4b9b3361

Ответ 1

В настоящее время это невозможно. Я еще не знаю причину (просто смотрю, потому что я нахожу это интересным). Обновление: вы можете найти причину в первом предложении для поддержки typedef-имен в качестве друзей: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1520.pdf. Причина в том, что стандарт поддерживает только спецификаторы специфицированного типа. Легко разрешить только те, и сказать, если объект, объявленный как друг, еще не объявлен, он станет членом окружающего пространства имен. Но это означает, что если вы хотите использовать параметр шаблона, вам придется делать (например, для этого требуется класс)

friend class T;

Но это привело к дополнительным проблемам, и это оказалось нецелесообразным. Теперь в документе предлагается предоставить дополнительные спецификаторы типов (чтобы затем использовать шаблонные параметры и typedef-имена).

Следующая версия С++ (из-за 2010 года) сможет это сделать.

См. это обновленное предложение к стандарту: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1791.pdf. Он не будет содержать только имена typedef, но также и параметры шаблона, которые будут использоваться как тип, объявленный как friend.

Ответ 2

Я попробовал в VС++ 8.0 код:

...
class C
{
public:
  friend class A;       
  friend X;             
  friend B::SUPERCLASS; 
};
...

Он компилируется без ошибок.

Я не знаю, зависит ли это от MS.

Ответ 3

AFAIK, В С++ typedef не создает полноценные синонимы при использовании в сочетании с классами. Другими словами, это не похоже на макрос.

Среди ограничений является то, что синоним не может появляться после префикса класса или структуры или использоваться как деструктор или имя конструктора. Вы также не можете подклассифицировать синоним. Я бы поспорил, что это также означает, что вы не можете его подружить.

Ответ 4

Тип typedef определяет тип. Друг объявляет объявлять классы или функции друзей (в основном области), которые затем имеют "доступ" к непубличной области объявляющего класса...

Примитивы, т.е. float или int * не определяют область с кодом и т.д. они все равно не "используют" класс.

Не забывайте, что вы также можете "упаковать" соглашения о вызовах, атрибуты выравнивания и другие специфичные для компилятора элементы в typedef, то есть несколько векторных TYPES, реализованных одним и тем же классом, но с различными атрибутами выравнивания. = > Тип не является классом, но наоборот.

IMHO, объявление друга typedef может быть полезным, но когда "class typedefs" из любого места можно установить как друга, дружба может стать чрезвычайно непонятной и, следовательно, подверженной ошибкам, особенно там, где шаблоны используются чрезмерно.

Недействительность одного typedef может испортить весь проект из-за широко распространенных зависимостей. Друзья шаблонов и шаблоны tyxefs 0x полезны, но не расслабляют правила объявления друга.

Я не знаю ни одного предложения, касающегося друг друга typedefs.

Ответ 5

class MyClass
{
    friend class ClassFromTypedef;

    // ...
};

не работает, пока

template<class T>
struct get_type{ typedef T type;};

class MyClass
{
    friend class get_type<ClassFromTypedef>::type;

    // ...
};

, похоже, работает для меня на gcc-4.6.0 с опцией -std = С++ 0x (я не знаю, насколько это важно). не работает... (Извините, я галлюцинировал)