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 > >