5

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:

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

Fedor
  • 17,146
  • 13
  • 40
  • 131
  • 2
    I don't see how 2 and 3 could possibly be true. Note that if you actually call `p` in `has_access`, then all compilers agree that 2 and 3 violate the access restriction. Looks like bugs in the requires-expression implementation to me. – user17732522 Jan 22 '22 at 12:03
  • Related https://stackoverflow.com/questions/53263299 – cigien Jan 22 '22 at 14:51

0 Answers0