On Fri, 12 Jul 2024 at 20:08, Dalbey, Keith <kdal...@sandia.gov> wrote: > > The means by which this FIX was implemented caused OTHER problems > > template <typename F, typename S> > std::ostream& operator<<(std::ostream& os, const std::pair<F,S>& pr) > { > os << "(" << pr.first << ", " << pr.second << ")"; > return os; > } > > Will only work for CONCRETE classes that take the place of "F" and "S" IFF > each of their concrete operator<< 's is FORWARD DECLARED ahead of the above > template, so primitives like int and double should still work, but if you > include this file in a header file that contains a concrete class that you > define an operator<< for, and then use in another file, you're SOL.
This is simply not true. #include <ostream> #include <utility> template <typename F, typename S> std::ostream& operator<<(std::ostream& os, const std::pair<F,S>& pr) { os << "(" << pr.first << ", " << pr.second << ")"; return os; } namespace ns { struct A { }; inline std::ostream& operator<<(std::ostream& out, const A& a) { return out << "A\n"; } } #include <iostream> int main() { std::pair<int, ns::A> p{}; std::cout << p; } This program works via ADL, because it uses namespaces correctly. If you dump all your operator overloads in the global namespace, then it doesn't work. So don't do that then.