Home > Mobile >  How to declare member template of class template as friend?
How to declare member template of class template as friend?

Time:04-01

Given the following code:

template <typename T, typename D> class B;

template <typename T>
class A {
public:
  A() { }
  template <typename D>
  A(B<T, D>);
};

template <typename T, typename D>
class B {
  friend A<T>::A(B<T, D>);
  int x;
};

template <typename T>
template <typename D>
A<T>::A(B<T, D> b) {
  b.x = 42;
}

int main() {
  B<int, double> b;
  A<int> a(b);
  return 0;
}

I want to declare member template A(B<T, D>) of class template A<T> as friend.

So I declared, friend A<T>::A(B<T, D>);

But I got a compile error:

test.cc: In instantiation of ‘class B<int, double>’:
test.cc:24:18:   required from here
test.cc:13:10: error: prototype for ‘A<int>::A(B<int, double>)’ does not match any in class ‘A<int>’
   friend A<T>::A(B<T, D>);
          ^~~~
test.cc:4:7: error: candidates are: constexpr A<int>::A(A<int>&&)
 class A {
       ^
test.cc:4:7: error:                 constexpr A<int>::A(const A<int>&)
test.cc:8:3: error:                 template<class D> A<T>::A(B<T, D>) [with D = D; T = int]
   A(B<T, D>);
   ^
test.cc:6:3: error:                 A<T>::A() [with T = int]
   A() { }
   ^
test.cc: In instantiation of ‘A<T>::A(B<T, D>) [with D = double; T = int]’:
test.cc:25:13:   required from here
test.cc:20:5: error: ‘int B<int, double>::x’ is private within this context
   b.x = 42;
   ~~^
test.cc:14:7: note: declared private here
   int x;
       ^

How to fix it?

CodePudding user response:

The important part of the error message seems to be this line:

test.cc:8:3: error:                 template<class D> A<T>::A(B<T, D>) [with D = D; T = int]

Notice how the template type D is not expanded to the actual type.

That lead me to believe that adding a new template type for the friend declaration might help:

template<typename U>
friend A<T>::A(B<T, U>);

And it works in my testing.


After thinking a little bit about the reasons behind this, I think it's because there's really no such (constructor) function as A::A(B<T, D>), only the template template<typename D> A::A(B<T, D>).

  • Related