使用模板将成员函数集声明为朋友

时间:2017-01-29 17:52:26

标签: c++ templates friend

给出以下代码:

class A;

struct B {
    static void doIt(A* pa);
};

struct C {
    static void doIt(A* pa);
};

class A {
    int i = 9;
    // below works but requires a line per each type
    friend void B::doIt(A* pa);
    friend void C::doIt(A* pa);

    // the below however doesn't work
    // template<typename T>
    // friend void T::doIt(A* pa);
      // (gcc error: member 'void T::doIt(A*)' declared as friend before type 'T' defined)
      // (clang just ignores the above and the error is on accessing A::i in B and C)    
};

void B::doIt(A* pa) {
    cout << pa->i << endl;
}

void C::doIt(A* pa) {
    cout << pa->i *2 << endl;
}

int main() {
    A a;
    B::doIt(&a);
    C::doIt(&a);
}

是否可以替换多个friend声明以允许所有void T::doIt(A* pa)方法访问A的私有成员?

尝试实例化B以及C以上的A并没有帮助。

3 个答案:

答案 0 :(得分:1)

不完全是你问的是什么,但......如果你对BC等结构进行模板化,你可以得到类似的东西。

#include <iostream>

class A;

template <std::size_t>
struct X
 { static void doIt(A* pa); };

class A
 {
    int i = 9;

    template <std::size_t I>
    friend void X<I>::doIt (A* pa);
 };

template <>
void X<0U>::doIt(A* pa)
 { std::cout << pa->i << std::endl; }

template <>
void X<1U>::doIt(A* pa)
 { std::cout << pa->i * 2 << std::endl; }

template <>
void X<2U>::doIt(A* pa)
 { std::cout << pa->i * 3 << std::endl; }

using B = X<0U>;
using C = X<1U>;
using D = X<2U>;

int main() {
    A a;
    B::doIt(&a);
    C::doIt(&a);
    D::doIt(&a);
}

答案 1 :(得分:1)

我相信使用CRTP和私有/受保护的虚拟继承可以完成类似于您的需求。下面的代码只是演示,肯定需要一些工作,例如不涉及模板方法友谊:

#include <iostream>

using namespace std;

class base {
protected:
    int i = 9;
};

template <class F>
class crtp_base: virtual base { // private inheritance!
    template <class T>
    friend void F::doIt(T*);
};

template <class... AllF>
struct crtp_bases: crtp_base<AllF>... { };

struct B {
    template <class T>
    static void doIt(T* pa);
};

struct C {
    template <class T>
    static void doIt(T* pa);
};

class A: public crtp_bases<B, C> {
};

template <class T>
void B::doIt(T* pa) {
    cout << pa->i << endl;
}

template <class T>
void C::doIt(T* pa) {
    cout << pa->i * 2 << endl;
}

int main() {
    A a;
    B::doIt(&a);
    //cout << a.i << endl; // error i is private member of 'base'
}

[live demo]

答案 2 :(得分:0)

我看不到直接的方法,但是一个解决方法可能是使用几个静态方法声明一个类(而不是使用一个静态方法的几个类),然后将此类声明为朋友,如:

...
struct D {
    static void doItB(A* pa);
    static void doItC(A* pa);
};

class A {
...
    friend struct D;
...
};

void D::doItB(A* pa) {
    cout << pa->i << endl;
}

...
    D::doItB(&a);
    D::doItC(&a);
...