Declaring a member function set as a friend using a template

Given the following code:

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); } 

Is it possible to replace multiple friend declarations so that all void T::doIt(A* pa) methods can access private members of A ?

Trying to instantiate B and C above A does not help.

+5
source share
3 answers

Not quite what you requested, but ... if you templatize structures B , C , etc., you can get something like this.

 #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); } 
+2
source

I believe that something similar to what you want can be done using CRTP and virtual private / protected inheritance. The code below is just a demo and definitely needs some work, for example. do not include friendship template style:

 #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 << ai << endl; // error i is private member of 'base' } 

[live demo]

+1
source

I do not see the direct path, but one workflow can declare one class with several static methods (instead of several classes with one static method), and then declare this class as a friend, for example:

 ... 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); ... 
0
source

Source: https://habr.com/ru/post/1263547/


All Articles