[EDIT - I long since forgot this was here until I got the 2,500 views "notable question". Since people are viewing - there is useful information about overloads in the accepted answer, but specifically checking for std::endl
is even worse than I realized at the time, and definitely the wrong thing.
Basically, the effect of std::endl
is to output \n
to the stream then flush with std::flush
. That's irrespective of platform, including Windows where the end-of-line is really "\r\n". The endl
manipulator doesn't abstract away platform differences WRT line ends, C++ handles that the same way that C does - by translating \n
to "\r\n" (for text mode, not binary) later on. I thought C++ was doing something different, an assumption so strong I never even questioned it for 2 decades, but I was wrong.
I don't remember details, but it's possible to define your own streams anyway, and provide alternative output (and translation) of whatever characters are streamed in. All manipulators should work as expected, before your custom stream code sees the resulting output characters. So to provide special end-of-line behaviour, watch for the \n
there (which is still before the text-file end-of-line translation).
]
It's hackish, I know, but I recently needed to implement a stream class which would act mostly like a standard stream, but which would detect the std::endl manipulator and special-case it's behaviour. My first attempt at a particular method implementation was...
mystream& mystream::operator<< (std::basic_ostream<char>& (*p) (std::basic_ostream<char>&))
{
if (p == &std::endl)
{
// Handle special case
}
else
{
m_Underlying_Stream << p;
}
return *this;
}
The trouble with this is that the compiler doesn't know which overload of std::endl
I'm referring to. I resolved it as follows...
mystream& mystream::operator<< (std::basic_ostream<char>& (*p) (std::basic_ostream<char>&))
{
typedef std::basic_ostream<char>& (*ENDL_T) (std::basic_ostream<char>&);
const ENDL_T l_ENDL (&std::endl);
if (p == l_ENDL)
{
// Handle special case
}
else
{
m_Underlying_Stream << p;
}
return *this;
}
That is the compiler can resolve the overload in the context of an initialisation (and for assignment too, as another experiment proved), but not for operator==
.
The compiler in question is MinGW GCC 4.4.0, but I don't think this is likely to be a compiler issue.
I had a look around and found this question...
How to get the address of an overloaded member function?
If my code has a const issue, I don't know where the missing const needs to go. I can't see any other obvious type issue.
I have some vague ideas about number-of-steps issues WRT overloading or implicit casting, but nothing concrete. So - can anyone explain clearly what is wrong with my first example, why the second version fixes it, and how I can safely indicate which overload I mean when taking the address of a function.
BTW - I can guess some people won't like me testing directly for the address of std::endl
, and will point out that this is fragile - e.g. someone could have their own manipulator which calls std::endl
which I wouldn't spot. In general this is true, but in this special case, the hack saves a lot of time and the nastiness just doesn't matter.