8

I'm trying to use variadic templates to specify friend classes. I try with the following syntax, but it doesn't work.

template <class... Args>
struct A {
    friend Args...;
};

I try to code some workarounds, but it seems to be not so simple since the friendship is not transitive and inherited. So the question is if there is a correct syntax or any workaround to make each individual class in Args be a friend of A?

John Zwinck
  • 239,568
  • 38
  • 324
  • 436
mattia.penati
  • 532
  • 5
  • 18
  • 2
    Args here is a list of types. A friend must be a specific class or function, not a list. What's an example use case here? – John Zwinck Apr 26 '14 at 02:46
  • I think the specific case is not relevant. The question is if the pack expansion syntax can be used in such situation. I don't find anything in the standard which explains or forbids such case. – mattia.penati Apr 26 '14 at 03:13
  • Sorry, in the section 14.5.3 there is a list of valid contexts and such situation is not included, so I hope in a workaround. – mattia.penati Apr 26 '14 at 03:20
  • So let me ask you again, what is the use case? Are you trying for example to make each element in Args be a friend? Because trying to make Args... be a friend is nonsensical, because Args is not a type nor a function. How could it be a friend and what would that mean? – John Zwinck Apr 26 '14 at 09:51
  • I want to make each type in the parameter pack friend of the class. The idea is that friend Args... syntax expands the pack. But the standard does not take into account this case. – mattia.penati Apr 26 '14 at 10:38

1 Answers1

4

Maybe the following CRTP variant would be sufficient for your use:

template<typename Arg> class Abase
{
  friend Arg;
  virtual int foo(int) = 0; // this is the private interface you want to access
public:
  virtual ~Abase() {}
};

template<typename... Args> class A:
  public Abase<Args> ...
{
  virtual int foo(int arg) { return frobnicate(arg); }
  // ...
}

Then each class you pass in Args can access that private interface through the corresponding Abase base class, for example

class X
{
public:
  // assumes X is in the Args
  template<typename Args ...> int foo(A<Args...>* p)
  {
    Abase<X>* pX = p; // will fail if X is not in Args
    return pX->foo(3); // works because X is friend of Abase<X>
  }
};
celtschk
  • 19,311
  • 3
  • 39
  • 64
  • I've coded a similar solution, using CRTP and static_cast, but as in your code it is mandatory to speficy the class from which you access to the protected member. Currently it seems to be the only solution. – mattia.penati Apr 26 '14 at 16:17