On Fri, Jul 26, 2024 at 06:00:12PM -0400, Patrick Palka wrote:
> 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"...

So, shall we file some https://github.com/cplusplus/CWG/ issue about this?
Whether the packs [temp.constr.fold] talks about are the normalized ones
only (in that case what happens if there are no packs), or all packs
mentioned (in that case, whether there shouldn't be also template parameter
mappings on the fold expanded constraints like there are on the atomic
constraints (for the unexpanded packs only)?

Interesting testcases could be also:
struct A <class ...T> {};
template <class T> C = true;
template <class T> D = __is_same (T, int);
template <class ...U, class ... V> requires ((C<U> && D<V>) && ...)
constexpr bool foo (A<U...>, A<V...>) { return true; }
static_assert (foo (A<int, int>, A<int, int, int>));
// Is this valid because only V unexpanded pack from the normalized
// constraint is considered, or invalid because there are 2 packs
// and have different length?

Anyway, I'm afraid on the implementation side, ARGUMENT_PACK_SELECT
didn't help almost at all.  The problem e.g. on fold-constr7.C testcase
is that the ARGUMENT_PACK_SELECT is optimized away before it could be used.
tsubst_parameter_mapping (where I could remove the
      if (cxx_dialect >= cxx26 && ARGUMENT_PACK_P (arg))
hack without any behavior change) just tsubsts it into int type.
With the hack removed, it will go through
      if (ARGUMENT_PACK_P (arg))
        new_arg = tsubst_argument_pack (arg, args, complain, in_decl);
but that still sets new_arg to int INTEGER_TYPE; while if a pack is used
in some nested pack expansion as well as outside of it, we'd need to arrange
to reconstruct ARGUMENT_PACK_SELECT in what tsubst_parameter_mapping
arranges.

        Jakub

Reply via email to