Пара вопросов:
Так же, как вы не ставите <T>
после имени класса при определении шаблона класса:
template <class T> class X<T> { ... }; // WRONG
template <class T> class X { ... }; // RIGHT
, вы не должны ставить егопосле имени класса при объявлении шаблона класса, будь то в предварительном объявлении или объявлении друга:
template <class T> class X<T>; // WRONG
template <class T> class X; // RIGHT - declares the template exists
template <class T> friend class X<T>; // WRONG
template <class T> friend class X; // RIGHT - says all specializations of X are friends
(Если вы не создаете частичную специализацию шаблона класса. Например, если шаблон класса X
уже объявлено, тогда template <class T> class X<T*> { ... };
определяет частичную специализацию, которая будет использоваться вместо основного шаблона, когда аргумент шаблона является указателем.)
И у вас есть объявление друга в обратном направлении: оно должно появиться внутри классас непубличным членом (членами), и назовите другой класс (ы), которым разрешено использовать члены.(Если бы это работало наоборот, то любой новый класс мог бы получить доступ к закрытым и защищенным членам любого другого класса без разрешения класса-владельца!)
Поэтому вам потребуется:
template <class T> class Foo;
template<class T> class Base {
template <class U> friend class Foo;
protected:
T container;
};
Предварительное объявление Foo
иногда не требуется, но я думаю, что оно делает вещи более понятными, и оно может избежать ошибок, когда вещи становятся более сложными с пространствами имен, вложенными классами и т. Д.