Шаблон класса с шаблоном друг, что здесь происходит? - PullRequest
71 голосов
/ 23 января 2012

Допустим, я создаю класс для двоичного дерева, BT, и у меня есть класс, который описывает элемент дерева, BE, что-то вроде

template<class T> class BE {
    T *data;
    BE *l, *r;
public:
...
    template<class U> friend class BT;
};

template<class T> class BT {
    BE<T> *root;
public:
...
private:
...
};

Это похоже на работу; однако у меня есть вопросы о том, что происходит под ним.

Я изначально пытался объявить друга как

template<class T> friend class BT;

однако здесь представляется необходимым использовать U (или что-то отличное от T), почему это так? Означает ли это, что какой-то конкретный BT является другом какого-либо конкретного BE класса?

На странице IBM, посвященной шаблонам и друзьям, есть примеры различных типов отношений друзей для функций, но не для классов (и предположение, что синтаксис еще не сработал в решении). Я бы предпочел понять, как правильно составить спецификации для типа дружеских отношений, которые я хочу определить.

Ответы [ 4 ]

95 голосов
/ 23 января 2012
template<class T> class BE{
  template<class T> friend class BT;
};

Недопустимо, поскольку параметры шаблона не могут затенять друг друга.Вложенные шаблоны должны иметь разные имена параметров шаблона.


template<typename T>
struct foo {
  template<typename U>
  friend class bar;
};

Это означает, что bar является другом foo независимо от аргументов шаблона bar.bar<char>, bar<int>, bar<float> и другие bar будут друзьями foo<char>.


template<typename T>
struct foo {
  friend class bar<T>;
};

Это означает, что bar является другом foo когда аргумент шаблона bar соответствует foo.Только bar<char> будет другом foo<char>.


В вашем случае friend class bar<T>; должно быть достаточно.

6 голосов
/ 23 июня 2016

Чтобы подружиться с другой структурой того же типа:

#include <iostream>

template<typename T_>
struct Foo
{
    // Without this next line source.value_ later would be inaccessible.
    template<typename> friend struct Foo;

    Foo(T_ value) : value_(value) {}

    template <typename AltT>
    void display(AltT &&source) const
    {
        std::cout << "My value is " << value_ << " and my friend's value is " << source.value_ << ".\n";
    }

protected:
    T_ value_;
};

int main()
{
    Foo<int> foo1(5);
    Foo<std::string> foo2("banana");

    foo1.display(foo2);

    return 0;
}

С выводом следующим образом:

My value is 5 and my friend's value is banana. 

В template<typename> friend struct Foo; вы не должны писать T после typename / class, иначе это вызовет ошибку затенения параметров шаблона.

3 голосов
/ 09 июля 2016

Не нужно называть параметры, чтобы при рефакторинге было меньше точек отказа:

     template <typename _KeyT, typename _ValueT> class hash_map_iterator{
       template <typename, typename, int> friend class hash_map;
       ...
0 голосов
/ 12 ноября 2014

В моем случае это решение работает правильно:

template <typename T>
class DerivedClass1 : public BaseClass1 {
  template<class T> friend class DerivedClass2;
private:
 int a;
};

template <typename T>
class DerivedClass2 : public BaseClass1 {
  void method() { this->i;}
};

Надеюсь, это будет полезно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...