https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101222
Bug ID: 101222 Summary: unwanted templated constructor instantiation due to wrong binary operator access Product: gcc Version: 12.0 Status: UNCONFIRMED Keywords: rejects-valid Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: vopl at bk dot ru Target Milestone: --- cat main.cpp && echo EOFFFFFF template<typename T> struct Trap {}; struct Some { template<typename T, int = sizeof(Trap<T>)> Some(T) {}// Trap for T - only for check if Some<T> was instantiated }; void operator<(const Some&, const Some&);//wrong instantiatoion of Some::Some<E> here enum E{}; int main() { bool b = E{} < E{};// wrong access to "bool operator<(const Some&, const Some&);" return 0; } template <> struct Trap<E> {};// now check Trap for E EOFFFFFF $ g++ -c main.cpp main.cpp:17:20: error: specialization of 'Trap<E>' after instantiation 17 | template <> struct Trap<E> {};// now check Trap for E | ^~~~~~~ main.cpp:17:20: error: redefinition of 'struct Trap<E>' main.cpp:1:29: note: previous definition of 'struct Trap<E>' 1 | template<typename T> struct Trap {}; | ^~~~ ------------------------------------------------- In these code "void operator<(const Some&, const Some&)" is not a candidate for overloading for "E{} < E{}", so, it must not be used at all, and as a result, Some::Some<E> must not be instantiated. All gcc versions with c++11 standard are affected. Clang and msvc are okay.