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>)
.