如何让方法访问其他模板类实例的私有成员?

Dar*_*ioP 8 c++ templates private-members

这极小的例子将无法编译,因为A<int>不能访问私有成员iA<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;
}
Run Code Online (Sandbox Code Playgroud)

我知道我可以让所有模板实例彼此成为朋友(参见:如何访问其他模板类实例的私有成员?),但由于我只有一个需要访问的方法(如示例所示),我更愿意限制友谊到那个方法.这可能吗?

Rei*_*ica 8

是的,这是可能的.会员功能通常可以指定为朋友.

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;
}
Run Code Online (Sandbox Code Playgroud)

实例(gcc one Ideone)


请注意,与gcc不同,clang拒绝代码.但是,我无法在标准中找到任何会使其无效的内容.


Mar*_* A. 6

似乎如果你想拥有一个朋友成员函数,以下内容将不适用于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;
}
Run Code Online (Sandbox Code Playgroud)

虽然它适用于gcc.

这个问题似乎是与代表友元类模板铛的问题,为其从属名称符不能在AST解决:http://llvm.org/klaus/clang/commit/8b0fa5241a0416fc50dfbb7e38f20e777f191848/(仍然是在后备箱的时候写这个).

因此,你可以使用上面的成员函数版本,虽然它可能不会在clang上工作,直到找到它.

计划B解决方案是让它具有免费的模板化朋友功能,虽然它可能不是你想要的(被cland和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;
}
Run Code Online (Sandbox Code Playgroud)

Example