This is the mail archive of the
mailing list for the GCC project.
Re: [c++-concepts] Constrained friends
- From: Jason Merrill <jason at redhat dot com>
- To: Andrew Sutton <andrew dot n dot sutton at gmail dot com>, gcc-patches at gcc dot gnu dot org, Gabriel Dos Reis <gdr at axiomatics dot org>
- Date: Sat, 21 Sep 2013 08:32:47 -0400
- Subject: Re: [c++-concepts] Constrained friends
- Authentication-results: sourceware.org; auth=none
- References: <CANq5SytNsrWf6e5WcX_uFqmYzAr9pBMi8gw16nuarbk+HkJ3Sw at mail dot gmail dot com>
On 09/13/2013 12:21 PM, Andrew Sutton wrote:
Previously, if constraints were not
satisfied, we would not record the template as a candidate. However,
this causes errors in class template instantiation if there are
constrained friend declarations whose constraints are not satisfied
("no matching template declaration").
Is that wrong? We normally give errors about friend declarations that
don't match any template. Why don't we want this error when the friend
declaration is looking for a constrained template?
+ if (is_non_template_member_fn (fn) || is_non_template_friend (fn))
Let's have one predicate instead of two; the condition here is a
temploid that is not a specialization of a primary template.
+ if (!check_template_constraints (tmpl, args) && (complain & tf_error))
reason = template_constraint_failure (tmpl, args);
viable = false;
Why add the complain check? A constraint failure should make a
candidate non-viable even in SFINAE context.
+ // If we're not instantiating a friend function, then we need to
+ // ensure the specialization of the best template satisfies its
+ // constraints.
Surely we need to check constraints in the earlier loop, so that we
don't treat as a candidate a template that doesn't satisfy the
constraints; otherwise if we have two templates
template <class T> T f(T) requires Thing;
template <class T> T* f(T*);
and our specialization requires Thing, we would select the second
(because it is otherwise more specialized) and then give an error about
constraint mismatch; I would think we want to select the first.
+ // If there is an overload with the same type and
+ // constraints, then this is a good declaration.
+ if (same_type_p (TREE_TYPE (fn), TREE_TYPE (f)))
+ if (equivalent_constraints (constr, get_constraints (f)))
It seems that this will only allow friend declarations that match the
template exactly, not friend declarations that are more specialized than
the matching template. It looks like you're trying to implement a
subset of determine_specialization here, which I think is a mistake.