템플릿 클래스 친구가있는 클래스 템플릿, 여기서 실제로 무슨 일이 일어나고 있습니까?


80

하자 내가, 이진 트리에 대한 클래스를 만드는거야라고 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 페이지에는 클래스가 아닌 함수에 대한 다른 유형의 친구 관계의 예가 있습니다 (그리고 구문이 아직 솔루션에 수렴되지 않았 음을 추측). 정의하고 싶은 친구 관계 유형에 맞는 사양을 얻는 방법을 이해하고 싶습니다.

답변:


111
template<class T> class BE{
  template<class T> friend class BT;
};

템플릿 매개 변수는 서로 섀도 잉 할 수 없으므로 허용되지 않습니다. 중첩 된 템플릿은 다른 템플릿 매개 변수 이름을 가져야합니다.


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

이것은 의 템플릿 인수 barfoo관계없이 친구 임을 의미합니다 bar. bar<char>, bar<int>, bar<float>, 및 기타이 bar의 친구가 될 것입니다 foo<char>.


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

이것은 의 템플릿 인수가의와 일치 할 때 bar의 친구 임을 의미합니다 . 의 친구 만 될 것입니다 .foobarfoobar<char>foo<char>


귀하의 경우에는 friend class bar<T>;충분합니다.


2
내 코드 친구 클래스 BT <T>의이 구성은 친구 줄 오류에 대한 오류를 발생시킵니다. 'BT'는 나중에 template <class T> 클래스 BT {...}로 선언되었지만 템플릿이 아닙니다.
Michael Conlen

2
그래서 비밀은 친구 클래스 BT <T>를 사용하기 위해 BT 선언을 전달해야한다는 것입니다. BE의 줄이지 만 template <class U> friend 클래스 BT;에는 해당되지 않습니다. 도와 주셔서 감사합니다!
Michael Conlen

24
좀 더 구체적으로 말하면 BE 정의 template<typename T> class BT; 전에 전달 선언 한 다음 BE 클래스 friend class BT<T>; 내부 에서 사용해야 합니다.
Bartosz Milewski 2013

7

다른 동일한 유형의 구조체와 친구가 되려면 :

#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;쓰면 안됩니다. 그렇지 않으면 템플릿 매개 변수 섀도 잉 오류가 발생합니다.Ttypenameclass


3
답변을 개선하십시오.
swiftBoy

정확히 내가 찾던 것! ;)
jihlim

3

매개 변수의 이름을 지정할 필요가 없으므로 리팩토링하는 경우 실패 지점을 줄일 수 있습니다.

     template <typename _KeyT, typename _ValueT> class hash_map_iterator{
       template <typename, typename, int> friend class hash_map;
       ...

-3

제 경우에는이 솔루션이 올바르게 작동합니다.

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;}
};

도움이 되었으면합니다.


6
템플릿 매개 변수를 섀도 잉하고 DerivedClass2의 친구 액세스 권한을 DerivedClass1에 사용하지 않을 때 해당 솔루션이 올바르게 작동하는 방법은 무엇입니까?
kornman00
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.