Variadic friend classes?

Is this possible? I'm pretty inexperienced with templates, variadic templates especially. I get a syntax error message from GCC 4.7 when I try to compile.

1
2
3
4
template<typename... Args>
struct test {
    friend class Args;
};
I don't think there's any way to make that work, even with only one argument. What are you trying to do?
> Is this possible?

It is possible, though the mechanism is somewhat convoluted.

a. place the non-public members (for which we want to grant access via friend declarations) as protected members in a base class.

b. inherit virtually from this base class (we want one and only one copy of these members).

c. recursively unpack and forward the types in the variadic template to base classes; each base class declaring the unpacked template type as a friend.

As a trivial example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
struct test_base { protected: int i ; } ;

template < typename... T > struct basic_test {} ;

// T is a friend of basic_test<T>, so T can access base::i inherited by basic_test<T>
template < typename T > struct basic_test<T> : virtual test_base { friend T ; } ;

// make FIRST and recursively every type in REST... friends of a base class
template < typename FIRST, typename... REST >
struct basic_test<FIRST,REST...> : basic_test<FIRST>, basic_test<REST...> {} ;

// every type in ARGS... is a friend of some base class or other
// therefore, every type in ARGS.. can access base::i inherited by test<ARGS...>
template < typename... ARGS > struct test : basic_test<ARGS...> {} ;

struct D
{
    void foo( test<int,D,double>& test_int_D_double )
    {
        test_int_D_double.i = 100 ; // fine; D is a friend of basic_test<D>
        // test<int,D,double> inherits from basic_test<D>
        // members and friends of D can access base::i inherited by test<int,D,double>
    }

    void bar( test<int,double>& test_int_double )
    {
        test_int_double.i = 100 ; // *** error: base::i is protected,
        // test<int,double> does not inherit from basic_test<D>
        // members or friends of D can't access base::i inherited by test<int,double>
    }
};

http://coliru.stacked-crooked.com/a/8a60e35e7e34617c

In general, look for alternatives to designs involving widestread use of friends.
Ah, I wasn't aware or forgot that you could use template parameters in friend declarations.
Came with C++11.
Where T is a template type parameter, just friend T ; not friend class T ;
Thanks for the help. I don't have a specific use for it in mind, I just wondered if it was possible.
Topic archived. No new replies allowed.