开发者

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).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜