Share std::fstream or std::stringstream trough std

2019-05-28 16:02发布

问题:

I have a function that creates std::stringstream or std::fstream depending on condition, like:

// Some class, stringStream_ and fileStream_ are members
// obj.Stream() returns std::iostream&
if (condition)
{
    stringStream_.str(std::string());
    obj->Stream().rdbuf(stringStream.rdbuf());
}
else
{
    boost::filesystem::path temp = boost::filesystem::unique_path();
    fileStream_.open(temp.native().c_str(), std::ios_base::trunc | std::ios_base::in | std::ios_base::out);
    obj->Stream().rdbuf(fileStream_.rdbuf());
}

and then this obj object is processed in another thread, so at this moment the function above may be called once more and streambuf in stringStream will be reset and fileStream_ will fail to open new file because it is associated with another one.

I can't make a function like obj.SetStream() because streams are non-copyable.

The question is: how can I create either std::stringstream or std::fstream and pass it to the object so the object becomes an owner of the stream (note object stores std::iostream because it doesn't know what type of stream will be passed).

Thanks in advance.

回答1:

You can pass around a pointer (raw or smart) to dynamically allocated instance of either std::fstream or std::stringstream typed as pointer to std::iostream. The client of the stream then just needs to do something like std::iostream & s = *iostreamPtr; s << "yay!"; to use it.



回答2:

You could just make this into a templated function

template<class T>
void yourFunc(T& object) 
{
  if (typeid(T) == typeid(std::stringstream))
  {
    stringStream_.str(std::string());
    obj->Stream().rdbuf(stringStream.rdbuf());
  }
  else
  {
    boost::filesystem::path temp = boost::filesystem::unique_path();
    fileStream_.open(temp.native().c_str(), std::ios_base::trunc | std::ios_base::in | std::ios_base::out);
    obj->Stream().rdbuf(fileStream_.rdbuf());
  }
}


标签: c++ stream c++03