https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98822

            Bug ID: 98822
           Summary: Rejects-valid: instantiation of class template
                    instantiates (all) constrained non-template friend
                    definitions (, even those) with unsatisfied
                    constraints
           Product: gcc
           Version: 11.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: davveston at gmail dot com
  Target Milestone: ---

(All standard references below refer to N4861).

Constrained hidden non-template friends was added as per NS US115 of P2103R0
(adding [temp.friend]/9), meaning the following program is (afaict)
well-formed:

 template<int N>
 struct S {
     friend void f(int) requires (N == 0) { }
     operator int() const { return 0; }
 };

 int main() { 
     f(S<0>{});
 }

whereas the following is ill-formed, as overload resolution rejects the friend
due to unsatisfied constraints:

 template<int N>
 struct S {
     friend void f(int) requires (N == 0) { }
     operator int() const { return 0; }
 };

 int main() { 
     f(S<1>{});
     // error: no matching function for call to 'f'
     // candidate function not viable: constraints not satisfied
 }

and GCC correctly accepts and rejects these two examples, respectively.

However, the following program is also rejected by GCC:

 template<int N>
 struct S {
     friend void f(int) requires (N == 0) { }
     operator int() const { return 0; }
 };

 S<1> s1{};
 S<2> s2{};
 // error: redefinition of 'void foo(int) requires  N == 0'

implying that GCC, for each instantiation of the class template S, also
instantiates its constrained friend definitions, even those where the
associated constraints are not satisfied, meaning more than a single
instantiation in a single TU fails due to and ODR-violation
([basic.def.odr]/1). It basically acts the same way as for hidden friend
definitions prior to constrained (non-templated) friends.

I have not been able to sort out whether the final example above is actually
well-formed as per N4861, but it's arguably weird if US115 added support for
constrained non-template (hidden) friends whilst not allowing overloading
solely on the constraint. As per [temp.friend]/9 each constrained hidden friend
is indeed unique (to its specialization), which is also supported by
[defns.signature.friend].

Constraint satisfaction should arguably be checked in the context of the
template instantiation and not only during overload resolution.

---

(MSVC accepts the final example above, but fails with ambiguous call errors
during overload resolution if we start overloading constrainded non-template
friends solely on their constraints. Clang has fails this feature for other
reasons; failing [defns.signature.friend] w.r.t. unique mangled names if we add
another overload with another constraint).

Reply via email to