8

This extremely minimal example will fail to compile because A<int> cannot access the private member i in A<double>

template <class T>
class A {
    int i;
  public:
    template <class U>
    void copy_i_from( const A<U> & a ){
        i = a.i;
    }
};

int main(void) {
    A<int> ai;
    A<double> ad;
    ai.copy_i_from(ad);
    return 0;
}

I know that I can make all the template instances friends of each other (see: How to access private members of other template class instances?), but since I have only one method that requires the access (like in the example) I would prefer to limit the friendship to that method. Is this possible?

Community
  • 1
  • 1
DarioP
  • 5,377
  • 1
  • 33
  • 52

2 Answers2

8

Yes, it's possible. Member functions can be designated as friends normally.

template <class T>
class A {
    int i;
  public:
    template <class U>
    void copy_i_from( const A<U> & a ){
        i = a.i;
    }
  template <class F>
  template <class U>
  friend void A<F>::copy_i_from(const A<U> & a);
};

int main(void) {
    A<int> ai;
    A<double> ad;
    ai.copy_i_from(ad);
    return 0;
}

Live example (gcc one Ideone)


Note that unlike gcc, clang rejects the code. I cannot find anything in the standard that would make it invalid, though.

Angew is no longer proud of SO
  • 167,307
  • 17
  • 350
  • 455
6

It seems that if you want to have a friend member function, the following won't work on clang:

template <class T>
class A {
    int i;
  public:
    template <class U>
    void copy_i_from( const A<U> & a ){
        i = a.i;
    }
  template <class F>
  template <class U> friend void A<F>::copy_i_from(const A<U> & a);
};

int main(void) {
    A<int> ai;
    A<double> ad;
    ai.copy_i_from(ad);
    return 0;
}

while it works on gcc.

The issue seems to be a clang's problem with representing friend class template for which the dependent name specifier cannot be resolved in the AST: http://llvm.org/klaus/clang/commit/8b0fa5241a0416fc50dfbb7e38f20e777f191848/ (still in trunk at the time of writing this).

Therefore you could go for the member function version above although it might not work on clang until this is figured out.

A plan-B solution is to have it a free templated friend function, although it might not be what you want (accepted by both cland and gcc):

#include <iostream>
using namespace std;

template <class T>
class A {
    int i;
public:
    template<class V, class U>
    friend void copy_i_from(A<V>& t, const A<U> & a);
};

template<class V, class U>
void copy_i_from(A<V>& t, const A<U> & a){
    t.i = a.i;
}

int main(void) {
    A<int> ai;
    A<double> ad;
    copy_i_from(ai,ad);
    return 0;
}

Example

Marco A.
  • 43,032
  • 26
  • 132
  • 246
  • 1
    I think that this was a valuable answer even before the edit (I felt bad when you deleted it), but now is even better! – DarioP Oct 17 '14 at 10:52