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.

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.

Reply via email to