Reputation: 21
I have a member that is a shared_ptr<ofstream>
.
In a specific case, I want to suppress the output, and making the stream a boost::iostreams::stream<boost::iostreams::null_sink>
. Should do what I want.
I would prefer to avoid the ofstream(nullptr)
suggested in this thread, it doesn't compile when wrapped in make_shared()
.
I'm open to other null ofstream
shared_ptr
suggestions, but it needs to be cross platform.
Initializing it with an output (non suppressed) works:
InputReader::InputReader(std::string filepath2, std::string filepathmain){
this->thestreamstruct.themainWriter = std::move(std::make_shared<std::ofstream>(filepathmain.c_str()));
}
In the suppressed initializer, I declare the null sink stream shared_ptr
instead of initializing the ofstream
, and then want to cast this to an ofstream
and assign it to the member:
InputReader::InputReader(std::string filepath2, Model* amodel){
std::shared_ptr<boost::iostreams::stream<boost::iostreams::null_sink>> nullOstream = std::make_shared<boost::iostreams::stream<boost::iostreams::null_sink>>((boost::iostreams::null_sink()));
std::shared_ptr<std::ofstream> nullost = std::move(std::dynamic_pointer_cast<std::ofstream>(nullOstream));
this->thestreamstruct.themainWriter = nullost;
}
This fails because there's no direct cast between std::ofstream
and the boost stream.
But I can assign an ofstream
ref as the boost null sink??
boost::iostreams::stream<boost::iostreams::null_sink> nullout { boost::iostreams::null_sink{} };
std::ostream& out = nullout;
This is fine, so there must be the underlying ofstream
somewhere? I just don't know how to get it wrapped up into a shared_ptr
.
Upvotes: 1
Views: 230
Reputation: 392833
Taking some pains to get life-time correct without leaking the buffer:
#include <boost/iostreams/device/null.hpp>
#include <boost/iostreams/stream_buffer.hpp>
#include <filesystem>
#include <fstream>
#include <iostream>
#include <memory>
using std::filesystem::path;
using sofstream = std::shared_ptr<std::ofstream>;
sofstream make_null() {
struct both {
boost::iostreams::stream_buffer<boost::iostreams::null_sink> b{{}};
std::ofstream ofs;
};
auto s = std::make_shared<both>();
static_cast<std::ios&>(s->ofs).rdbuf(&s->b);
return sofstream(s, &s->ofs);
}
sofstream make(path p) { return std::make_shared<std::ofstream>(p); }
int main() {
for (auto ss : { make_null(), make("test.txt") }) {
*ss << "hello world\n";
assert(ss->good());
*ss << "bye world\n";
assert(ss->good());
}
}
I personally think this whole approach might be to clever by half and you should use std::ostream&
instead of std::ofstream&
anyways. (e.g. http://coliru.stacked-crooked.com/a/333cc9871c5e977b)
Upvotes: 0