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()
istrue
in all compilers I tested.A<1>::has_access()
istrue
in Clang only.A<char(0)>::has_access()
istrue
in 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>
?