On Tue, 5 Nov 2024, Jason Merrill wrote:

> On 10/17/24 1:10 PM, Patrick Palka wrote:
> > On Thu, 17 Oct 2024, Patrick Palka wrote:
> > 
> > > On Tue, 15 Oct 2024, Patrick Palka wrote:
> > > 
> > > > On Tue, 15 Oct 2024, Patrick Palka wrote:
> > > > 
> > > > > According to [temp.param]/11, the constraint on an auto NTTP is an
> > > > > associated constraint and so should be checked as part of satisfaction
> > > > > of the overall associated constraints rather than checked individually
> > > > > during coerion/deduction.
> > > > 
> > > > By the way, I wonder if such associated constraints should be relevant
> > > > for
> > > > subsumption now?
> > > > 
> > > >      template<class T> concept C = true;
> > > > 
> > > >      template<class T> concept D = C<T> && true;
> > > > 
> > > >      template<C auto V> void f(); // #1
> > > >      template<D auto V> void f(); // #2
> > > > 
> > > >      int main() {
> > > >        f<0>(); // still ambiguous?
> > > >      }
> > > > 
> > > > With this patch the above call is still ambiguous despite #2 now being
> > > > more constrained than #1 because "more constrained" is only considered
> > > > for
> > > > function templates with the same signatures as per
> > > > https://eel.is/c++draft/temp.func.order#6.2.2 and we deem their
> > > > signatures
> > > > to be different due to the different type-constraint.
> > > 
> > > I think I convinced myself that this example should be accepted, and the
> > > way to go about that is to replace the constrained auto in the NTTP type
> > > with an ordinary auto once we set its TEMPLATE_PARM_CONSTRAINTS.  That
> > > way both templates have the same signature modulo associated constraints.
> > 
> > Here is v2 which implements this in finish_constrained_parameter.  Now
> > we can assert that do_auto_deduction doesn't see a constrained auto
> > during adc_unify deduction!
> > 
> > -- >8 --
> > 
> > Subject: [PATCH v2 2/2] c++: constrained auto NTTP vs associated constraints
> > 
> > According to [temp.param]/11, the constraint on an auto NTTP is an
> > associated constraint and so should be checked as part of satisfaction
> > of the overall associated constraints rather than checked individually
> > during coerion/deduction.
> > 
> > In order to implement this we mainly need to make handling of
> > constrained auto NTTPs go through finish_constrained_parameter so that
> > TEMPLATE_PARM_CONSTRAINTS gets set on them, and teach
> > finish_shorthand_constraint how to build an associated constraint
> > corresponding to the written type-constraint.
> > 
> > @@ -18637,24 +18609,43 @@ finish_constrained_parameter (cp_parser *parser,
> >                                 cp_parameter_declarator *parmdecl,
> >                                 bool *is_non_type)
> >   {
> > -  tree decl = parmdecl->decl_specifiers.type;
> > +  tree constr = parmdecl->decl_specifiers.type;
> >     tree id = get_unqualified_id (parmdecl->declarator);
> >     tree def = parmdecl->default_argument;
> > -  tree proto = DECL_INITIAL (decl);
> >       /* Build the parameter. Return an error if the declarator was invalid.
> > */
> >     tree parm;
> > -  if (TREE_CODE (proto) == TYPE_DECL)
> > -    parm = cp_parser_constrained_type_template_parm (parser, id, parmdecl);
> > +  if (is_constrained_auto (constr))
> > +    {
> > +      /* Constrained non-type parameter.  */
> > +      *is_non_type = true;
> 
> Why not replace constr with an unconstrained auto here...
> 
> > +      parm = grokdeclarator (parmdecl->declarator,
> > +                        &parmdecl->decl_specifiers,
> > +                        TPARM, /*initialized=*/0, /*attrlist=*/NULL);
> > +      /* Replace the type of this constrained (auto) NTTP with an ordinary
> > +    auto; its constraint gets saved in TEMPLATE_PARM_CONSTRAINTS to be
> > +    associated with the template.  */
> > +      if (parm != error_mark_node)
> > +   TREE_TYPE (parm) = (AUTO_IS_DECLTYPE (constr)
> > +                       ? make_decltype_auto ()
> > +                       : make_auto ());
> 
> ...rather than here?  Doing it here seems unlikely to work for e.g.
> 
> template <class T> concept C = __is_same(T,int);
> template <C auto *P> struct A { };
> int i;
> A<&i> a;
> 
> Hmm, I suspect finish_shorthand_constraint just taking decltype(P) will also
> break.

Good point, it does break.  It's not clear how to express and ultimately
mangle the constraint on P as an associated constraint.  I guess we
could do C<decltype(*P)> for C auto*, but then what about for C auto&
(where we must check C on the referred-to type)?

> 
> Jason
> 
> 

Reply via email to