Problem with overriding "operator <<" in a class derived from "ostream"

I want to create a class based on "ostream" that does auto formatting to create comma delimited files or tables. My idea was to override the "operator <to insert a separator before each value (except at the beginning and end of a line) and to quote lines before writing them. Inside the override" operator <method, I wanted to call the base class, but I can't get it to work correctly.

Here's an example (compiles with g ++ 4.3.3):

#include <iostream>
#include <ostream>
#include <string>

using namespace std;

class MyStream: public ostream
{
public:
  MyStream(ostream& out): ostream(out.rdbuf()) {}

  template <typename T> MyStream& operator<<(T value)
  {
    ostream::operator<<('+');
    ostream::operator<<(value);
    ostream::operator<<('+');
    return *this;
  }
};

template<> MyStream& MyStream::operator<< <string>(string value)
{
  ostream::operator<<('*');
  ostream::write(value.c_str(), value.size()); // ostream::operator<<(value);
  ostream::operator<<('*');
  return *this;
}

int main()
{
  MyStream mystr(cout);
  mystr << 10;
  cout << endl;
  mystr << "foo";
  cout << endl;
  mystr << string("test");
  cout << endl;
  return 0;
}

      

Two "operator <methods (pattern and specialization) to treat strings differently than everything else. But:

  • Characters ('+' / '*') are printed as numbers, not symbols.
  • The C-String "foo" prints as a memory address (I think).
  • If the string "write" is exchanged with a comment, the compiler complains that "there is no corresponding function to call in" MyStream :: operator <"(std :: string &)", even though I thought I was explicitly calling a base class method.

What am I doing wrong? Any help was much appreciated.

+2


source share


2 answers


Overloads operator<<

that print strings and characters are free functions. But since you are forcing the member functions to be called, you will force them to convert to one candidate of member functions declared in ostream

. For '*'

he will probably use overloading int

, and for "foo"

he will probably use overloading const void*

.



I would not inherit ostream

, but instead store it ostream

as a referenced element and then pass it from operator<<

to it. I would also not make a operator<<

member, but rather a free function template, not specialize, but overload operator<<

for std::string

and char const*

.

+5


source


Perhaps something like the following:

turn on



#include <ostream>
#include <string>

using namespace std;

class MyStream: public ostream
{
public:
    MyStream(ostream& out): ostream(out.rdbuf()) {}

    template <typename T> MyStream& operator<<(const T& value)
    {
        (ostream&)*this << '+' << value << '+';
        return *this;
    }
    MyStream& operator<< (const string& value)
    {
        (ostream&)*this << '*' << value << '*';
        return *this;
    }
    MyStream& operator<< (const char* cstr)
    {
        (ostream&)*this << '(' << cstr << ')';
        return *this;
    }
};

      

+2


source







All Articles