I am trying to create a thin wrapper over an ostringstream instance which delegates all insertion operations to the enclosed ostringstream instance. The idea is to preserve type when doing cascading insertion operations. Normally the resulting type of a cascading insertion operation is ostream&, and any original type is lost. I'd like to maintain the type of the expression, because I want to be able to pass it to a method for further processing, and would like to have access to the underlying ostringstream to get at the string data that was inserted.
I'd like to be able to do something like the following, and have the result of the expression be LgStream:
LgStream() << 26 << " a plain string " << std::string("a std string") << someObjWithItsOwnInsertionOperator;
So I defined operator<<() for basic types, and template methods as a catch-all for everything else:
class LgStream
{
public:
ostringstream m_oss;
string str() {return m_oss.str();}
LgStream &operator<<(int x) {m_oss << x; return *this;}
LgStream &operator<<(long x) {m_oss << x; return *this;}
LgStream &operator<<(char x) {m_oss << x; return *this;}
LgStream &operator<<(bool x) {m_oss << (x ? 'T':'F'); return *this;}
LgStream &operator<<(double x) {m_oss << x; return *this;}
template <typename T>
LgStream &operator<<(const T &x) {m_oss << x; return *this;}
template <typename T>
LgStream &operator<<(const T x) {m_oss << x; return *this;}
};
I don't have it right, and am getting "ambiguous overload" errors. For example:
LgStream() << "This is a plain string";
error: ambiguous overload for 'operator<<' in 'LgStream() << "This is a plain string"'
note: candidates are:
note: LgStream& LgStream::operator<<(int) <near match>
note: no known conversion for argument 1 from 'const char [23]' to 'int'
note: LgStream& LgStream::operator<<(long int) <near match>
note: no known conversion for argument 1 from 'const char [23]' to 'long int'
note: LgStream& LgStream::operator<<(char) <near match>
note: no known conversion for argument 1 from 'const char [23]' to 'char'
note: LgStream& LgStream::operator<<(bool)
note: LgStream& LgStream::operator<<(std::string)
note: LgStream& LgStream::operator<<(const T&) [with T = char [23], LgStream = LgStream]
note: LgStream& LgStream::operator<<(T) [with T = const char*, LgStream = LgStream]
Any help appreciated with either syntax, or if I am taking the wrong approach.