On Fri, Jul 12, 2024 at 12:10 PM Dalbey, Keith via Gcc <gcc@gcc.gnu.org> 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; > }
You could just do: ``` template <typename F, typename S> std::ostream& operator<<(std::ostream& os, const std::pair<F,S>& pr); .... //include all other headers template <typename F, typename S> std::ostream& operator<<(std::ostream& os, const std::pair<F,S>& pr) { os << "(" << pr.first << ", " << pr.second << ")"; return os; } ``` And then it will work correctly. But now this is getting into C++ help rather than GCC help really. Thanks, Andrew > > 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. > > If you mix that with templated operator<< for vectors and std::shared_ptr > then there's a chicken and the egg problem for which STL templated operator<< > gets declared first/ but you can work around this by FORWARD declaring all of > your operator<< (including the concrete and templated ones) before > **Defining** the STL templated operator<< 's, but that means the header file > containing the STL templated operator<< 's can never be included in another > header file and it can only be included as *the absolute last header file* in > a .cpp file (so that all the concrete operator<< get declared before them, > and you may still need to forward declare some of the contents of the .cpp > file ahead of including this header file) > > But really a header file that can't be included in other header files and can > only be included as the absolute last header file in a .cpp file is a > unreasonable set of hoops to jump through to get TEMPLATED operator<< 's to > work, which should just work BECAUSE THEY'RE TEMPLATES > > -----Original Message----- > From: Jonathan Wakely <jwakely....@gmail.com> > Sent: Friday, July 12, 2024 12:37 PM > To: Dalbey, Keith <kdal...@sandia.gov> > Cc: gcc@gcc.gnu.org > Subject: [EXTERNAL] Re: g++12 broke my system of overloaded operator<< > > [You don't often get email from jwakely....@gmail.com. Learn why this is > important at https://aka.ms/LearnAboutSenderIdentification ] > > On Fri, 12 Jul 2024 at 01:03, Dalbey, Keith via Gcc <gcc@gcc.gnu.org> wrote: > > > > So I'm on redhat 7 and just got devtoolsset-12 and code (a system of > > overloaded<< operators) that was working with devtoolset-10 now break > > (because of ordering) > > > > To not bury the lead.. > > > > My code relies on the version 11 or older behavior (see below), and I don't > > see how anyone could call the new behavior an improvement or correction > > because it neuters/cancels out the power/flexibility of the STL. Yes one > > could technically work around it by forward declaring templated operator<< > > but that makes the system not extensible, a common package/gitlab project > > that handles this for the STL and then gets succeed into another library > > that overloads the operator<< for concrete classes just doesn't work any > > more... and that was my exact use case. > > > > Please reverse this change in future editions of gcc, it is absolutely > > awful. > > Why would you want the example below to behave differently for > operator+(t, 0) and t+0 when they're two different ways to spell the > same function call? > > The old behaviour was clearly a bug, and thankfully has been fixed. > See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51577 for the bug report I > made about it years ago, which has a large number of duplicates because other > people also reported the old behaviour as a bug. Because it was a bug, and > people wanted GCC to follow the C++ standard. > > I'm sorry you've written code that depends on a bug, but we're not going to > break GCC again to restore the bug. > > > > > > From this link > > https://deve/ > > lopers.redhat.com%2Farticles%2F2022%2F04%2F25%2Fnew-c-features-gcc-12% > > 23corrections_and_internal_improvements&data=05%7C02%7Ckdalbey%40sandi > > a.gov%7Cc1e76e1166844e639bc208dca2a1aa33%7C7ccb5a20a303498cb0c12900738 > > 1b574%7C1%7C0%7C638564062475549377%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4 > > wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C0%7C%7C%7C&s > > data=KxNgv9u%2BDq8toLCNArhF1xjc1tHoP2Dy%2BYEv5P2gMXo%3D&reserved=0 > > Corrections and internal improvements > > The changes described in this section bring GCC more in line with recent > > changes to the standard, and permit behavior that previously did not work > > correctly. > > Dependent operator lookup changes > > GCC 12 corrected a problem where the compiler performed an unqualified > > lookup for a dependent operator expression at template definition time > > instead of at instantiation time. The fix matches the existing behavior for > > dependent call expressions. Consider the following test case demonstrating > > this change: > > #include <iostream> > > > > namespace N { > > struct A { }; > > } > > > > void operator+(N::A, double) { > > std::cout << "#1 "; > > } > > > > template<class T> > > void f(T t) { > > operator+(t, 0); > > t + 0; > > } > > > > // Since it's not visible from the template definition, this > > later-declared // operator overload should not be considered when > > instantiating f<N::A>(N::A), // for either the call or operator expression. > > void operator+(N::A, int) { > > std::cout << "#2 "; > > } > > > > int main() { > > N::A a; > > f(a); > > std::cout << std::endl; > > } > > Copy snippet > > This program will print #1 #2 when compiled with versions 11 or older of > > GCC, but GCC 12 correctly prints #1 #1. That's because previously only the > > call expression resolved to the #1 overload, but with GCC 12 the operator > > expression does too.