Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to let a method access private members of other template class instances?

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?

like image 478
DarioP Avatar asked Oct 17 '14 09:10

DarioP


People also ask

How do you access private members of a class from another class?

We can access private method in other class using the virtual function, A virtual function is a member function which is declared within a base class and is re-defined (Overridden) by a derived class.

How Do You can access the private data members of an instance?

To access, use and initialize the private data member you need to create getter and setter functions, to get and set the value of the data member. The setter function will set the value passed as argument to the private data member, and the getter function will return the value of the private data member to be used.

Can a template method be a member of a non template class?

It's not the method that is templated, it's the class. You can have a templated method in a non-templated class, a non-templated method in a templated class (your case) and a templated method in a templated class, and of course a non-templated method in a non-templated class. Save this answer.

Can we access private data members of a class without using a member or a friend function in C ++?

In C++, a friend function or friend class can also access private data members. So, is it possible to access private members outside a class without friend? Yes, it is possible using pointers.


2 Answers

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.

like image 81
Angew is no longer proud of SO Avatar answered Oct 26 '22 13:10

Angew is no longer proud of SO


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

like image 22
Marco A. Avatar answered Oct 26 '22 14:10

Marco A.