Thanks, this clears things up (sorry for the botched formatting of the original mail).This also explains why clang handles the code the same way as g++12. Regards Klaus Am Sonntag, 22. Mai 2022, 20:22:28 MESZ hat Jonathan Wakely <jwakely.gcc@xxxxxxxxx> Folgendes geschrieben: On Sun, 22 May 2022 at 18:25, Klaus Lindemann via Gcc-help <gcc-help@xxxxxxxxxxx> wrote: > > Hello, > was the handling of templates changed for g++12? I've run across some programs > which did compile with e.g. g++8, g++11, but no longer compile with g++12. > The fix is quite easy, but I wonder if this change is a bug, or a more strict > implementation of the standard. > Here is a short example program:================================================// compiles with g++ 11, not g++ 12 > #include <vector>namespace NN // if namespace is removed (i.e. global namespace is used), problem does not occur{ class OStr {};} > template <class T> NN::OStr& operator<<(NN::OStr& lhs, const std::vector<T>& rhs) { return lhs << rhs[0]; } > // moving this definition before the other template definition fixes gcc 12 compile problemtemplate <class T> NN::OStr& operator<< (NN::OStr& lhs, const T& rhs) { return lhs << rhs; } > int main(){ std::vector<int> a; NN::OStr os; os << a; return 0;}================================================= Reformatted so it's not illegible: #include <vector> namespace NN // if namespace is removed (i.e. global namespace is used), // problem does not occur { class OStr {}; } template <class T> NN::OStr& operator<<(NN::OStr& lhs, const std::vector<T>& rhs) { return lhs << rhs[0]; } // moving this definition before the other template definition // fixes gcc 12 compile problem template <class T> NN::OStr& operator<< (NN::OStr& lhs, const T& rhs) { return lhs << rhs; } int main(){ std::vector<int> a; NN::OStr os; os << a; return 0; } GCC 12 is correct. Your code is wrong. In the expression lhs << rhs[0], name lookup is done for operator<< by considering the overloads already visible at that point, and overloads that can be found by ADL in the associated namespaces. The associated namespaces for OStr and int are NN, and there is no viable overload in namepace NN. An operator that is part of the API of NN::OStr should be defined in namespace NN, not the global namespace. If you define both your operator<< overloads in the same namespace as class OStr it will work. N.B. this lookup is consistent for the non-template case, because GCC 12 has been fixed to stop looking in the global namespace when that is not an associated namespace.