https://gcc.gnu.org/bugzilla/show_bug.cgi?id=112288

--- Comment #8 from Patrick Palka <ppalka at gcc dot gnu.org> ---
The issue was probably latent before r6-6830.  The testcase is kind of strange,
e.g. 'slot_allocated' is defined within 'allocate_slot' instead of within
'slot', which would arguably be more natural given that its 'slot<T>' function
parameter.  And consecutive equivalent calls to 'next' apparently resolve to
different overloads due to 'slot_allocated' being defined only after we
instantiate the second 'next' overload.

Reduced:

template<class T>
struct slot {
  template<class U>
  friend constexpr bool slot_allocated(slot<T>, U);
};

template<class T>
struct allocate_slot {
  template<class U>
  friend constexpr bool slot_allocated(slot<T>, U) { return true; }
};

template<class T, bool = slot_allocated(slot<T>{}, 0)>
constexpr int next(int) { return 0; }

template<class T>
constexpr int next(...) { allocate_slot<T> s; return 42; }

// slot_allocated<slot<int>, int>() not defined yet
static_assert(next<int>(0) == 42);
// now it's defined
static_assert(next<int>(0) == 0);

Reply via email to