Hello,

Currently libstdc++ violates ODR:
iostream:     extern ostream cout;
global_io.cc:  fake_ostream cout;

It assumes that gcc will work fine with this. Apparently it does, for now.
After solving a similar problem in my code using a similar technique - to find out that it does not work for MS VS-2005 - when I had to find a different fix.

The question is, why does GCC has to resolve to such construction-order issue this way?

Idea (which I used):
don't violate ODR in global_io.cc. Instead, construct and destroy std::cout two times, in a safe way:

static PreSecondCtor coutPreSecondCtor(std::cout);
ostream std::cout(NULL);
static PostSecondCtor coutPostSecondCtor(coutPreSecodCtor);

When PreSecondCtor saves all relevant data of cout (error bits, state, rdbuf, etc.),
and then calls std::cout.~ostream();
Note that before this point, std::cout has already been constructed by an std::ios::Init,
and we need to avoid double construction.

In PostSecondCtor, restore the state of cout out of the saved data in outPreSecondCtor.

During destruction the order is reversed.

I still have a vague feeling that this solution is also undefined (since we are calling the constructor of std::cout, using placement new, after it had been automatically destroyed by the C++ environment). I don't have the standard near me, so I can't check.

Anyway, even if this is undefined, the situation is arguably better since it does not seem to break whole program compilation (like current implementation might).

What do you think?

Michael

Reply via email to