1

I need an interface to write short messages to a log file, the messages often contains multiple parts such as an identifier together with a value.

In order to do this I've created a class that handles a lot of minor stuff such as creating filenames with timestamps and so on, although I don't want to use a variable argument list (int nargs, ...), so I thought my best option was to pass a std::stringstream to the write function instead.

I want to be able to write these calls as one-liners and not having to create a std::stringstream every time I need to do this, therefore I created a static member function to return a stringstream object I could use with my write function, although for some reason it doesn't work.

MyClass.h

class MyClass {
public:

    static std::stringstream& stream();
    void write(std::ostream& datastream);

private:

    static std::stringstream* _stringstream;

};

MyClass.cpp

std::stringstream* MyClass::_stringstream = new std::stringstream();

std::stringstream& MyClass::stream() {
    MyClass::_stringstream->str(std::string());
    return *MyClass::_stringstream;
}

void MyClass::write(std::string data) {
    this->_fhandle << data << std::endl;
}

void MyClass::write(std::ostream& datastream) {
    std::string data = dynamic_cast<std::ostringstream&>(datastream).str();
    this->write(data);
}

main.cpp

MyClass* info = new MyClass();
info->write("Hello, world");
info->write(MyClass::stream() << "Lorem" << ", " << "ipsum");
info->write(MyClass::stream() << "dolor sit" << " amet");

The code compiles, but when executing the application I get a std::bad_cast exception...

John Smith
  • 133
  • 1
  • 1
  • 6

1 Answers1

2

That's because you are creating an std::stringstream, which doesn't derive from an std::ostringstream. Just create an std::ostringstream, and the bad_cast should disappear.

Having said that, reusing the std::ostringstream many times like this is generally not a good idea; the iostream classes are full of state, which will not be reset between each use. It's better to create new instance each time. (The classical solution for this sort of thing is to create a copiable wrapper class, which forwards to an std::ostream. An instance of this is returned by info->write(), so you can write info->write() << "Hello, world" ....)

James Kanze
  • 150,581
  • 18
  • 184
  • 329