Rudolfs Bundulis
Rudolfs Bundulis

Reputation: 11954

basic_ostream::operator<< char ambiguity between basic_ostream and custom class

Consider this example:

#include <sstream>
#include <ctime>

using MyStream = std::stringstream;

struct MyTime
{
    explicit MyTime(std::time_t time) // w/o explicit the MyTime operator << is ambigous as well
    {
    }
};

/*

having this overload of course solves everything, but that seems wrong

std::stringstream &operator<<(std::stringstream &stream, char c)
{
    stream.put(c);
    return stream;
}
*/

MyStream& operator<<(MyStream &stream, std::time_t time)
{
    return stream;
}

MyStream& operator<<(MyStream &stream, const MyTime &time)
{
    return stream;
}

int main(int argc, char **argv)
{
    MyStream stream;
    stream << 'Z';
    return 0;
}

Without having the std::stringstream &operator<<(std::stringstream &stream, char c) declaration, the stream << 'Z' fails with abmiguity (since there is no overload for char, it can be promoted to both short and hit basic_ostream and to time_t and hit MyStream). I don't really want to use basic_ostream::put) since the chaining of multiple writes would then look ugly (of course if that is the last resort then...). So this gives me two questions:

  1. What is the rationale of not having a char overload for basic_ostream::operator<< ? Is that all down to character encodings?
  2. Are there any nice solutions (something that I am missing apart from using put or having the char overload)?

UPDATE

So it seems that inheriting from std::stringstream vs using using fixes the issue, but this leaves me with the dilemma of going against the "never inherit from stl classes" dogma.

I guess the issue arises from the fact that using does not actually introduce a new type, thus the ambiguity:

A type alias declaration introduces a name which can be used as a synonym for the type denoted by type-id. It does not introduce a new type and it cannot change the meaning of an existing type name.

Upvotes: 1

Views: 88

Answers (1)

Jarod42
Jarod42

Reputation: 218323

You might fix issue by implementing overload with std::ostream instead of std::stringstream

std::ostream& operator<<(std::ostream &stream, std::time_t )
{
    return stream;
}

std::ostream& operator<<(std::ostream &stream, const MyTime &)
{
    return stream;
}

Demo.

Upvotes: 1

Related Questions