https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106281
Bug ID: 106281 Summary: Order failed overload candidates so ones with wrong number of params and inaccessible ones come last Product: gcc Version: unknown Status: UNCONFIRMED Keywords: diagnostic Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: redi at gcc dot gnu.org Target Milestone: --- template<class A, class B> class C { public: C() = default; template<class AA, class BB> C(AA, BB) { } C(C&&) = default; private: struct __secret_tag { }; template<class AA, class BB> C(AA&, BB&, __secret_tag) { } }; C<int, int> c({}, {}); We get these errors: cons.C:20:21: error: no matching function for call to ‘C<int, int>::C(<brace-enclosed initializer list>, <brace-enclosed initializer list>)’ 20 | C<int, int> c({}, {}); | ^ cons.C:16:5: note: candidate: ‘template<class AA, class BB> C<A, B>::C(AA&, BB&, __secret_tag) [with BB = AA; A = int; B = int]’ 16 | C(AA&, BB&, __secret_tag) | ^ cons.C:16:5: note: template argument deduction/substitution failed: cons.C:20:21: note: candidate expects 3 arguments, 2 provided 20 | C<int, int> c({}, {}); | ^ cons.C:8:5: note: candidate: ‘template<class AA, class BB> C<A, B>::C(AA, BB) [with BB = AA; A = int; B = int]’ 8 | C(AA, BB) | ^ cons.C:8:5: note: template argument deduction/substitution failed: cons.C:20:21: note: couldn’t deduce template parameter ‘AA’ 20 | C<int, int> c({}, {}); | ^ cons.C:11:3: note: candidate: ‘constexpr C<A, B>::C(C<A, B>&&) [with A = int; B = int]’ 11 | C(C&&) = default; | ^ cons.C:11:3: note: candidate expects 1 argument, 2 provided cons.C:5:3: note: candidate: ‘constexpr C<A, B>::C() [with A = int; B = int]’ 5 | C() = default; | ^ cons.C:5:3: note: candidate expects 0 arguments, 2 provided The first candidate shown: - is private - requires 3 parameters and only 2 args were used - is the last one defined in the class What is the logic that makes that come first? A private constructor that takes a "secret" third parameter of a type that is also private to the class is probably not what the user code was trying to use! The second candidate is the one being called. It is public and has the right number of args. It should be shown first (although the "[with BB = AA;" is nonsense, it's claiming that the arg subsitituting the first param is the second param ... wat?). Clang shows a more useful order, although still not the order they're declared in the class, so it still seems arbitrary: cons.C:20:13: error: no matching constructor for initialization of 'C<int, int>' C<int, int> c({}, {}); ^ ~~~~~~ cons.C:8:5: note: candidate template ignored: couldn't infer template argument 'AA' C(AA, BB) ^ cons.C:11:3: note: candidate constructor not viable: requires 1 argument, but 2 were provided C(C&&) = default; ^ cons.C:2:7: note: candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 2 were provided class C ^ cons.C:16:5: note: candidate constructor template not viable: requires 3 arguments, but 2 were provided C(AA&, BB&, __secret_tag) ^ cons.C:5:3: note: candidate constructor not viable: requires 0 arguments, but 2 were provided C() = default; ^