On Wed, May 7, 2025 at 2:44 AM Arthur O'Dwyer wrote:
>
> There is; check out the "passkey idiom."
> https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2893r3.html#passkey-idiom
I read your paper just now. I wonder had you considered excluding
certain classes with a 'requires' clause? Let's say you only want to
be friends with classes that have a 'value' that is a pointer to a
polymorphic class. So where you had:
template<class... Ts>
class Foo {
friend Ts...;
};
Imagine if you could have:
template<class... Ts>
class Foo {
(friend Ts requires (is_pointer_v< Ts::value > &&
is_polymorphic_v< remove_pointer_t<Ts::value> >) ). . . ;
};
Something along those lines.
That thing with the parentheses isn't remotely how C++'s declaration grammar works, though, so, no.
It might be plausible to befriend a bunch of template specializations by pretending to befriend an explicit specialization or partial specialization, like this:
template<class> struct A;
class B {
static int f();
template<> friend struct A<int>; // invalid today, but hypothetically this could become legal
template<class T> requires (sizeof(T) == 1) friend struct A<T>; // invalid today, but hypothetically this could become legal
};
template<> struct A<int> {
static int g(B *b) { return b->f(); } // hypothetically, this would become accessible
};
template<> struct A<char> {
static int g(B *b) { return b->f(); } // even more hypothetically, this would become accessible (even though the befriender used partial-specialization syntax and this is an explicit specialization)
};
template<> struct A<short> {
static int g(B *b) { return b->f(); } // remains ill-formed because B::f is inaccessible to this specialization
};
But that has nothing to do with "variadic friend"; that would be a completely different feature, completely different syntax.
–Arthur