std::ofstream file("log.txt");
std::stringstream ss;
DataStorage ds({file, std::cout, ss});
ds.Store("Hello, world!\n", 14);
std::cout << "ss contains: " << ss.str();
Note that with this approach, you again only store references in the DataStorage
class, making it store the concrete stream objects by value would be muchis more complicated, involving templates. It would look something like this:
template<typename... Ts>
class DataStorage {
public:
DataStorage(Ts&&... streams): streams(std::move(streams)...) {}
void Store(const char *buffer, std::size_t count) {
std::apply([=](Ts&... streams) {
(streams.write(buffer, count), ...);
}, streams_);
}
template<std::size_t I>
auto& Get() {
return std::get<I>(streams_);
}
private:
std::tuple<Ts...> streams_;
}
An issue here is that you cannot copy C++ IO streams, you can only take a reference or move them. The above will work when you pass in new objects:
DataStorage ds(std::ofstream("log.txt"), std::stringstream{});
ds.write("Hello, world!\n", 14);
std::cout << "ss contains: " << ds.Get<1>().str();
But you cannot do this:
DataStorage ds(std::cout, ...);
At least not without adding further complications to the code.