In the following code, there is template struct A with not-type template argument, and class B declares A<0> as its friend. Then the member function A<x>::has_access() is used to check that it has access to private B::p():
template<auto>
struct A {
static constexpr bool has_access();
};
class B {
void p() {}
friend struct A<0>;
};
template<auto x>
constexpr bool A<x>::has_access() {
return requires(B b) { b.p(); };
}
// #1: accepted by all
static_assert( A<0>::has_access() );
// #2: accepted by Clang
static_assert( A<1>::has_access() );
// #3: accepted by Clang and MSVC
static_assert( A<char(0)>::has_access() );
The program acceptance diverges:
A<0>::has_access()istruein all compilers I tested.A<1>::has_access()istruein Clang only.A<char(0)>::has_access()istruein Clang and MSVC only.
Demo: https://gcc.godbolt.org/z/P5njvzGee
Which compiler is right here? How many specializations of A must become friends of B after friend struct A<0>?