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