0

I'm facing problems with friend class templates. Here's how my code looks like

template<typename T>
class A{
private:

  template<typename U>
  friend class A;

  int m_num = 0;

public:
//...

};

while

template <typename T>
class B{
private:

  template<typename U>
  friend class B;

  template<typename U>
  friend class A; // Set A as friend class template of B

public:

  template<typename U>
  int GetNumOfA(const A<U>& a){
    return a.m_num; // Cannot Access A's private member!
  }

};

I expected A's private members to be accessible since I declared A as friend class of B. But it couldn't access it. Could you help me figure out why this happens? Or any ideas to make m_num accessible from B?

Justin
  • 41
  • 5
  • In `A`, when you write `friend class A;`, did you mean `B`? That should make this all work...and I'm not sure what the good of making a class a friend of itself is. – scohe001 Dec 31 '19 at 18:20
  • 1
    Probably an X/Y problem, `friend`ship is very intrusive - perhaps a rethink of what you're trying to accomplish and thinking of a better design. – Paul Evans Dec 31 '19 at 18:20
  • Which compiler and flags did you use? I dont seem to receive any similar errors https://godbolt.org/z/vkEHPn – Empty Space Dec 31 '19 at 18:21
  • 1
    @Mutable did you try to actually call the function? https://ideone.com/7iz3cA – scohe001 Dec 31 '19 at 18:21
  • 1
    @scohe001 you're right. How silly of me. – Empty Space Dec 31 '19 at 18:23

1 Answers1

0

You have it the wrong way around. You want B to be friend of A. So you need to declare B a friend in A's definition:

template<typename T>
class A{

//...

  template<typename U>
  friend class B;

//...

};

Do however think about whether you actually want all of these classes and their different specializations to be friend. The point of making a member private is that it represents a state internal to the class and should not be accessed directly by unrelated code. Usually, if you need direct access to a member, then you should either make it public or if there is a class invariant that doesn't allow that, give access to it through a public member function which preserves the invariant.

walnut
  • 21,629
  • 4
  • 23
  • 59
  • 2
    `There is also absolutely no point to making a class friend of itself.` This code is different I [think](https://stackoverflow.com/a/3292852/12160191). [Example](https://godbolt.org/z/maiq5z) – Empty Space Dec 31 '19 at 18:31
  • @MutableSideEffect Yes right, I didn't realize that. But it is unlikely that OP actually wants all of the specializations to be friends, anyway. – walnut Dec 31 '19 at 18:42
  • @walnut Oh, I was just silly.. thank you! As you mentioned, reason for making friend for the same class itself was to make all template specializations to be friends. – Justin Jan 01 '20 at 01:42