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