C++ overloaded operator resolution
g++ 4.4.5
I have a class that extends the class std::ofstream to add some functionality.
MyStream& MyStream::operator<<(const bool& val) {
if(this->pos == 8) {
this->pos = 0;
ofstream::operator<<(this->curbyte); //call the parent method
}
curbyte = curbyte + (val << pos++);
return *(this);
}
which basically allows you to write individual bits as bools and then it will write each set of 8 using the parent << method. I had to use this calling syntax here because I was calling the base method but in my actual main method where I use this class I tried to call the following line:
开发者_开发问答bout << (unsigned char) 255u;
which I want to have call the << method already defined for ofstream and unsigned char but it gives me a long ambiguous overload error listing all the char related candidates already defined for ofstream (char, unsigned char, signed char) and my own bool method, even though I explicitly cast to char. However I did manage to get it to work with the following:
bout.operator<<((unsigned char) 255u);
This must have something to do with how g++ does the implicit casting (my guess is there's one more possible cast after my user-defined cast in the first case which makes it ambiguous that the function call syntax avoids). Does anyone know exactly why this is happening or if there's a better syntax that avoids the error?
The operator<<
in std::ostream
that are defined as member functions aren't virtual
. Your operator<<
hides all of the base class versions of this function so they are not visible for overload resolution. However, the operator<<
which are defined as free functions are visible.
The operator<<
which take char
, unsigned char
and signed char
are all free functions.
This means that in bout << (unsigned char) 255u
your member function and the free function taking an unsigned char
are both visible for overload resolution.
To call the free function taking an unsigned char
, your class instance has to be bound to a reference to a base class, and this counts as a 'Conversion' but the right hand side requires no conversion. To call your member function, the unsigned char
has to be converted to a bool
- again a 'Conversion' but the left hand side requires no conversion. Neither of these conversion sequences is better than the other so the call is ambiguous.
This is a common blunder for people who are new to iostreams, i.e. deriving a new stream type because you want to output the data in a different way.
You also cannot add your own manipulations, i.e. you cannot extend iomanip.
The correct way to output data in a different format is to put a wrapper around the data you wish to output:
ostream& os << my_formatter(t);
for different types of t.
You can then have my_formatter as a template function that just returns t, unless it has been specialised. You can also give it multiple arguments. (It would return a class containing a reference to the underlying data, and would have operator<< overloaded).
精彩评论