On Fri, 26 Jul 2024, Jakub Jelinek wrote:

> On Fri, Jul 26, 2024 at 04:42:36PM -0400, Patrick Palka wrote:
> > > // P2963R3 - Ordering of constraints involving fold expressions
> > > // { dg-do compile { target c++20 } }
> > > 
> > > template <class ...T> concept C = (__is_same (T, int) && ...);
> > > template <typename V>
> > > struct S {
> > >   template <class ...U> requires (C<U...>)
> > >   static constexpr bool foo () { return true; }
> > > };
> > > 
> > > static_assert (S<void>::foo <int, int, int, int> ());
> > > 
> > > somehow the template parameter mapping needs to be remembered even for the
> > > fold expanded constraint, right now the patch will see the pack is T,
> > > which is level 1 index 0, but args aren't arguments of the C concept,
> > > but of the foo function template.
> > > One can also use requires (C<int, int, int>) etc., no?
> > 
> > It seems the problem is FOLD_EXPR_PACKS is currently set to the
> > parameter packs used inside the non-normalized constraints, but I think
> > what we really need are the packs used in the normalized constraints,
> > specifically the packs used in the target of each parameter mapping of
> > each atomic constraint?
> 
> But in that case there might be no packs at all.
> 
> template <class T> C = true;
> template <class ...U> requires (C<T> && ...)
> constexpr bool foo () { return true; }
> 
> If normalized C<T> is just true, it doesn't use any packs.
> But the [temp.constr.fold] wording assumes it is a pack expansion and that
> there is at least one pack expansion parameter, otherwise N wouldn't be
> defined.

Hmm yeah, I see what you mean.  That seems to be an edge case that's not
fully accounted for by the wording.

One thing that's unclear to me in that wording is what are the pcak
expansion parameters of a fold expanded constraint.

In

  template<class... T> concept C = (__is_same (T, int) && ...);
  template<class U, class... V>
  void f() requires C<V...>;

is the pack expansion parameter T or V?  In

  template<class... T> concept C = (__is_same (T, int) && ...);
  template<class U>
  void g() requires C<U>;

it must be T.  So I guess in both cases it must be T.  But then I reckon
when [temp.constr.fold] mentions "pack expansion parameter(s)" what it
really means is "target of each pack expansion parameter within the
parameter mapping"...

Reply via email to