Since it is by design that std::ostream can't be moved the question becomes: how can an std::ostream be moved such that it can write to different destinations?
The basic objective is to have a factory function taking a URI and returning something, let's call it, omstream (output movable stream) which can be used like an std::ostream:
omstream stream_factory(std::string const& uri);
void process(std::ostream& out);
int main(int ac, char* av[]) {
omstream destination{ stream_factory(ac == 2? av[1]: "example.txt") };
process(destination);
}
The omstream would be responsible for properly moving the object:
class omstream
: public std::ostream {
// suitable members
public:
omstream(/* suitable constructor arguments */);
omstream(omstream&& other) // follow recipe of 27.9.1.11 [ofstream.cons] paragraph 4
: std:ios(std::move(other))
, std::ostream(std::move(other))
// move any members {
this->set_rdbuf(/* get the stream buffer */);
}
// other helpful or necessary members
};
The question is really what it takes to implement omstream (or, even a corresponding class template basic_omstream)?
You've almost got it right. Your example is move constructing the ios base twice. You should move only the direct base class. And assuming there is member streambuf, move that too:
class omstream
: public std::ostream {
// suitable members
public:
omstream(/* suitable constructor arguments */);
omstream(omstream&& other) // follow recipe of 27.9.1.11 [ofstream.cons] paragraph 4
: std: ostream(std::move(other)),
// move any members {
this->set_rdbuf(/* install the stream buffer */);
}
// other helpful or necessary members
};
I changed "get" to "install" in the set_rdbuf comment. Typically this installs a pointer to the member streambuf into the ios base class.
The current unorthodox design of the move and swap members of istream/ostream was set up to make the move and swap members of the derived classes (such as ofstream and omstream) more intuitive. The recipe is:
Move the base and members, and in the move constructor set the rdbuf.
It is that embedded rdbuf that is the complicating factor for the entire hierarchy.
The code posted in Howard's answer is a draft (based on the draft posted in the question). Howard's answer helped resolving a confusing issue with the virtual base class std::ios: the base class needs to be default constructed when moving a derived stream as the std::ios portion of a stream will explicitly be moved by the std::ostream move constructor using std::ios::move(). This answer merely fills in the missing bits.
The implementation below maintains a pointer to a stream buffer which normally expected to live on the heap and will be released upon destruction with the help of std::unique_ptr<...>. As it may be desirable to return an std::omstream the stream buffer of a long-lived stream, e.g., std::cout, the std::unique_ptr<...> is set up to use a deleter which may do nothing if the omstream doesn't own the stream buffer.
#include <ostream>
#include <memory>
#include <utility>
template <typename cT, typename Traits = std::char_traits<cT>>
class basic_omstream
: public std::basic_ostream<cT, Traits>
{
using deleter = void (*)(std::basic_streambuf<cT, Traits>*);
static void delete_sbuf(std::basic_streambuf<cT, Traits>* sbuf) {
delete sbuf;
}
static void ignore_sbuf(std::basic_streambuf<cT, Traits>*) {
}
std::unique_ptr<std::basic_streambuf<cT, Traits>, deleter> m_sbuf;
public:
basic_omstream()
: std::basic_ios<cT, Traits>()
, std::basic_ostream<cT, Traits>(nullptr)
, m_sbuf(nullptr, &ignore_sbuf) {
}
basic_omstream(std::basic_streambuf<cT, Traits>* sbuf,
bool owns_streambuf)
: std::basic_ios<cT, Traits>()
, std::basic_ostream<cT, Traits>(sbuf)
, m_sbuf(sbuf, owns_streambuf? &delete_sbuf: &ignore_sbuf) {
this->set_rdbuf(this->m_sbuf.get());
}
basic_omstream(basic_omstream&& other)
: std::basic_ios<cT, Traits>() // default construct ios!
, std::basic_ostream<cT, Traits>(std::move(other))
, m_sbuf(std::move(other.m_sbuf)) {
this->set_rdbuf(this->m_sbuf.get());
}
basic_omstream& operator=(basic_omstream&& other) {
this->std::basic_ostream<cT, Traits>::swap(other);
this->m_sbuf.swap(other.m_sbuf);
this->set_rdbuf(this->m_sbuf.get());
return *this;
}
};
typedef basic_omstream<char> omstream;
typedef basic_omstream<wchar_t> womstream;
Using an std::ofstream or an std::ostringstream to initialize an omstream doesn't work unless the corresponding stream outlives the omstream. In general a corresponding stream buffer will be allocated. The class omstream could, e.g., be used like in the code below which create a stream based on an URI given to a suitable factory function:
#include <iostream>
#include <sstream>
#include <fstream>
omstream make_stream(std::string const& uri) {
if (uri == "stream://stdout") {
return omstream(std::cout.rdbuf(), false);
}
else if (uri == "stream://stdlog") {
return omstream(std::clog.rdbuf(), false);
}
else if (uri == "stream://stderr") {
return omstream(std::cerr.rdbuf(), false);
}
else if (uri.substr(0, 8) == "file:///") {
std::unique_ptr<std::filebuf> fbuf(new std::filebuf);
fbuf->open(uri.substr(8), std::ios_base::out);
return omstream(fbuf.release(), true);
}
else if (uri.substr(0, 9) == "string://") {
return omstream(new std::stringbuf(uri.substr(9)), true);
}
throw std::runtime_error("unknown URI: '" + uri + "'");
}
int main(int ac, char* av[])
{
omstream out{ make_stream(ac == 2? av[1]: "stream://stdout") };
out << "hello, world\n";
}
If there are other stream buffers available which could be constructed from a URI, these could be added to the make_stream() function.
Related
I have a base class which writes objects to a std::ostream with buffering. I want to call this with
Obj obj;
flat_file_stream_writer<Obj> writer(std::cout);
writer.write(obj);
writer.flush();
but also with
Obj obj;
flat_file_writer<Obj> writer("filename.bin");
writer.write(obj);
writer.flush();
The latter call must establish a std::ofstream instance, and hold that for the duration of writing, and can then call the former version.
I thought simple non-virtual inheritance would be fine here. But I have constructor initialization order issues.
warning: field 'ofstream_' will be initialized after base
'flat_file_stream_writer<hibp::pawned_pw>' [-Wreorder-ctor]
Because the base class depends on a reference to the object held by the derived this seems like chicken and egg and can't be solved?
Is inheritance just the wrong abstraction here? A clean alternative?
template <typename ValueType>
class flat_file_stream_writer {
public:
explicit flat_file_stream_writer(std::ostream& os, std::size_t buf_size = 100)
: db_(os), buf_(buf_size) {}
void write(const ValueType& value) {
if (buf_pos_ == buf_.size()) flush();
std::memcpy(&buf_[buf_pos_], &value, sizeof(ValueType));
++buf_pos_;
}
void flush() { // could also be called in destructor?
if (buf_pos_ != 0) {
db_.write(reinterpret_cast<char*>(buf_.data()), // NOLINT reincast
static_cast<std::streamsize>(sizeof(ValueType) * buf_pos_));
buf_pos_ = 0;
}
}
private:
std::ostream& db_;
std::size_t buf_pos_ = 0;
std::vector<ValueType> buf_;
};
template <typename ValueType>
class flat_file_writer : public flat_file_stream_writer<ValueType> {
public:
explicit flat_file_writer(std::string dbfilename)
: dbfilename_(std::move(dbfilename)), dbpath_(dbfilename_),
ofstream_(dbpath_, std::ios::binary), flat_file_stream_writer<ValueType>(ofstream_) {
if (!ofstream_.is_open())
throw std::domain_error("cannot open db: " + std::string(dbpath_));
}
private:
std::string dbfilename_;
std::filesystem::path dbpath_;
std::ofstream ofstream_;
};
You can put std::ofstream ofstream_; in a separate struct, then have flat_file_writer inherit from that struct using private. Base classes are initialized in the order they are declared, so make sure to inherit from that struct before flat_file_stream_writer. You can now initialize that ofstream_ before the base class flat_file_stream_writer.
On closer inspection, I think you'll probably want to put all 3 of those members in the struct.
See below for updated code.
So this in effect means that the 3 members in ofstream_holder now come before the flat_file_stream_writer in the layout of flat_file_writer.
This seems like the right solution, not just because it "squashes the compiler warning", but because now we are really getting the correct initialization order, ie construct the std::ofstream first and then pass a reference to it to flat_file_stream_writer. And during destruct the std::ofstream will be destroyed last.
The original code above had this exactly the wrong way around, because the order we write in the derived constructor initializer is ignored and the actual order implemented is layout order, ie the order the members are declared.
(despite the flaws of the original code, it "ran fine" for me with sanitizers etc... but was probably UB?).
template <typename ValueType>
class flat_file_stream_writer {
public:
explicit flat_file_stream_writer(std::ostream& os, std::size_t buf_size = 100)
: db_(os), buf_(buf_size) {}
void write(const ValueType& value) {
if (buf_pos_ == buf_.size()) flush();
std::memcpy(&buf_[buf_pos_], &value, sizeof(ValueType));
++buf_pos_;
}
void flush() {
if (buf_pos_ != 0) {
db_.write(reinterpret_cast<char*>(buf_.data()), // NOLINT reincast
static_cast<std::streamsize>(sizeof(ValueType) * buf_pos_));
buf_pos_ = 0;
}
}
private:
std::ostream& db_;
std::size_t buf_pos_ = 0;
std::vector<ValueType> buf_;
};
struct ofstream_holder {
explicit ofstream_holder(std::string dbfilename)
: dbfilename_(std::move(dbfilename)), dbpath_(dbfilename_),
ofstream_(dbpath_, std::ios::binary) {}
std::string dbfilename_;
std::filesystem::path dbpath_;
std::ofstream ofstream_;
};
template <typename ValueType>
class flat_file_writer : private ofstream_holder, public flat_file_stream_writer<ValueType> {
public:
explicit flat_file_writer(std::string dbfilename)
: ofstream_holder(std::move(dbfilename)), flat_file_stream_writer<ValueType>(ofstream_) {
if (!ofstream_.is_open())
throw std::domain_error("cannot open db: " + std::string(dbpath_));
}
};
Lately I've taken interest in initialization. One of the things I'm particularly interested in, is std::optional for its ability to initialize an instance of a type after it's been declared. I have tried reading the code inside the optional header, but the code is just too 'bombastic' for me to comprehend.
How is std::optional able to delay the initialization of an object on the stack? I assume it just reserves sizeof(<whichever_type) number of bytes on the stack, and then reinterprets those bytes for the initialization of <whichever_bytes>. But how does it do that specificially? How is it implemented? How can I implement that myself?
Edit: to clarify, I know that std::optional basically has a bool member to keep track of whether the object is initialized or not, and another member, which contains the data.
What I don't understand, however, is how optional is able to manually initialze something.
How is it able to destruct an object? How is it able to reconstruct a new one again after the old one is destructed?
The "obvious" way to represent an std::optional<T> is to use an indication whether the value is set together with a union containing a T, i.e., something like this:
template <typename T>
class optional {
bool isSet = false;
union { T value; };
public:
// ...
};
By default the members in the union are not initialized. Instead, you'll need to use placement new and manual destruction to manage the life-time of the entity within the union. Conceptually that is similar to using an array of bytes but the compiler handles any alignment requirements.
Here a program with some of the operations shown:
#include <iostream>
#include <memory>
#include <string>
#include <utility>
#include <cassert>
template <typename T>
class optional {
bool isSet = false;
union { T value; };
void destroy() { if (this->isSet) { this->isSet = true; this->value.~T(); } }
public:
optional() {}
~optional() { this->destroy(); }
optional& operator=(T&& v) {
this->destroy();
new(&this->value) T(std::move(v));
this->isSet = true;
return *this;
}
explicit operator bool() const { return this->isSet; }
T& operator*() { assert(this->isSet); return this->value; }
T const& operator*() const { assert(this->isSet); return this->value; }
};
int main()
{
optional<std::string> o, p;
o = "hello";
if (o) {
std::cout << "optional='" << *o << "'\n";
}
}
I am writing a class that has various messages output. I want to make this class general and platform independent, so I am thinking of passing a basic_ostream reference to it and it can dump all the messages into the stream. By doing this, if the class is used in a console program, I can pass std::cout to it and display in console window.
Or I could pass a derived ostream to it and redirect the message to some UI components, e.g. ListBox? The only problem is the data inserter operator << is not a virtual function. If I pass the derived class reference to it, only the basic_ostream << operator will be called.
Is there any workaround for this?
Nan Zhang's own answer, originally posted as part of the question:
Follow up: OK, here is the derived std::streambuf that implements required functionality:
class listboxstreambuf : public std::streambuf {
public:
explicit listboxstreambuf(CHScrollListBox &box, std::size_t buff_sz = 256) :
Scrollbox_(box), buffer_(buff_sz+1) {
char *base = &buffer_.front();
//set putbase pointer and endput pointer
setp(base, base + buff_sz);
}
protected:
bool Output2ListBox() {
std::ptrdiff_t n = pptr() - pbase();
std::string temp;
temp.assign(pbase(), n);
pbump(-n);
int i = Scrollbox_.AddString(temp.c_str());
Scrollbox_.SetTopIndex(i);
return true;
}
private:
int sync() {
return Output2ListBox()? 0:-1;
}
//copying not allowed.
listboxstreambuf(const listboxstreambuf &);
listboxstreambuf &operator=(const listboxstreambuf &);
CHScrollListBox &Scrollbox_;
std::vector<char> buffer_;
};
To use this class just create a std::ostream and initialize with this buffer
std::ostream os(new listboxstreambuf(some_list_box_object));
This question already has answers here:
Standard no-op output stream
(6 answers)
Closed 2 years ago.
I'd like to send data to nowhere, I mean that I don't want to print data in console nor in file, but I need some std::ostream object. How to do that?
I've used:
std::ostream bitBucket(0);
recently without problems, although it was flagged as having some potential problems if you looked at it from a certain angle (see the link below).
Aside: From what I understand (and I'm not entirely sure of this), that call above eventually ends up calling basic_ios::init(0) and, because that's a NULL pointer being passed in, it sets the stream state, as returned by the rdstate() function, to the badbit value.
This in turn prevents the stream from outputting any more information, instead just tossing it away.
The following program shows it in action:
#include <iostream>
int main (void) {
std::ostream bitBucket(0);
bitBucket << "Hello, there!" << std::endl;
return 0;
}
The page where I got it from also had this as a probably-cleaner solution (slightly modified to remove the duplication of my first solution above):
#include <iostream>
class null_out_buf : public std::streambuf {
public:
virtual std::streamsize xsputn (const char * s, std::streamsize n) {
return n;
}
virtual int overflow (int c) {
return 1;
}
};
class null_out_stream : public std::ostream {
public:
null_out_stream() : std::ostream (&buf) {}
private:
null_out_buf buf;
};
null_out_stream cnul; // My null stream.
int main (void) {
std::cout << std::boolalpha;
//testing nul
std::cout << "Nul stream before: " << cnul.fail() << std::endl;
cnul << "Goodbye World!" << std::endl;
std::cout << "Nul stream after: " << cnul.fail() << std::endl;
}
The simplest solution is just to output to an unopened std::ofstream
(or any other output stream in an error state). This will result in the
stream being permanently in an error state. This could be an advantage
(<< operators will skip the formatting), but if any code that you
can't control checks for errors, and does something particular if they
occur, you'll likely have problems.
Otherwise, it's pretty simple to implement a null stream; the only
streambuf function you really have to override is overflow.
Something like the following should do the trick:
class NulStreambuf : public std::streambuf
{
char dummyBuffer[64];
protected:
virtual int overflow( int c )
{
setp( dummyBuffer, dummyBuffer + sizeof( dummyBuffer ) ) ;
return (c == EOF) ? '\0' : c ;
}
};
(The buffer will avoid some unnecessary virtual function calls. On some
platforms, this makes a significant difference.)
Then create an output stream which uses it:
class NulOStream : public NulStreambuf, public std::ostream
{
public:
NulOStream() : std::ostream( this ) {}
};
(The use of inheritance, rather than containment, ensures that the
streambuf is fully constructed before being passed to the ostream.
This generally isn't necessary in practice, but the standard doesn't
seem to authorize passing a not yet constructed streambuf to the
constructor of ostream.)
Simplest solution: Use a std::stringstream.
#include <sstream>
#include <iostream>
void func(std::ostream& o){
o << "blatest\n";
}
int main(){
std::stringstream black_hole;
func(std::cout);
func(black_hole);
}
The stringstream will contain the output, but if you don't use it, it's the same as if it was never filled.
Since nobody mentioned it, if it's about suppressing std or error output, you can simply close the corresponding file descriptors (e.g. fclose (stdout) or fclose (stderr)).
That will shup up everything, including things like printf or fprintf (stderr, ...)
So you will indeed keep using the usual cout or cerr, but they will be turned into bit buckets.
Some suggestions here: http://bytes.com/topic/c/answers/589209-std-null-stream
A good answer from that site:
Use ordinary std::fstream, open it only for writing to required file
"/dev/null". It should work.
If you really want to create own stream, just derive it from
basic_ostream and simply define your own operator<< to be function
which only returns stream reference. You will have to write dummy
'write' and 'put' method too (and all other methods for output).
#include <streambuf>
#include <ostream>
template <class cT, class traits = std::char_traits<cT> >
class basic_nullbuf: public std::basic_streambuf<cT, traits> {
typename traits::int_type overflow(typename traits::int_type c)
{
return traits::not_eof(c); // indicate success
}
};
template <class cT, class traits = std::char_traits<cT> >
class basic_onullstream: public std::basic_ostream<cT, traits> {
public:
basic_onullstream():
std::basic_ios<cT, traits>(&m_sbuf),
std::basic_ostream<cT, traits>(&m_sbuf)
{
init(&m_sbuf);
}
private:
basic_nullbuf<cT, traits> m_sbuf;
};
typedef basic_onullstream<char> onullstream;
typedef basic_onullstream<wchar_t> wonullstream;
From http://bytes.com/topic/c/answers/428285-null-ostream
I have a map which represents a configuration. It's a map of std::string and boost::any.
This map is initialized at the start and I'd like the user to be able to override these options on the command line.
What I'd love to do is build the program options from this map using the options_description::add_option() method. However, it takes a template argument po::value<> whereas all I have is boost::any.
So far, I just have the shell of the code. m_Config represents my configuration class, and getTuples() returns a std::map<std::string, Tuple>. TuplePair is a typedef of std::pair<std::string, Tuple> and the Tuple contains the boost::any I am interested in.
po::options_description desc;
std::for_each(m_Config.getTuples().begin(),
m_Config.getTuples().end(),
[&desc](const TuplePair& _pair)
{
// what goes here? :)
// desc.add_options() ( _pair.first, po::value<???>, "");
});
Is there a way to build it this way, or do I need to resort to doing it myself?
Thanks in advance!
boost::any is not applicable to your problem. It performs the most basic form of type erasure: storage and (type-safe) retrieval, and that's it. As you've seen, no other operations can be performed. As jhasse points out, you could just test every type you want to support, but this is a maintenance nightmare.
Better would be to expand upon the idea boost::any uses. Unfortunately this requires a bit of boiler-plate code. If you'd like to try it, there's a new Boost library being discussed right now on the mailing list (titled "[boost] RFC: type erasure") that is essentially a generalized type erasure utility: you define the operations you'd like your erased type to support, and it generates the proper utility type. (It can simulate boost::any, for example, by requiring the erased type be copy-constructible and type-safe, and can simulate boost::function<> by additionally requiring the type be callable.)
Aside from that, though, your best option is probably to write such a type yourself. I'll do it for you:
#include <boost/program_options.hpp>
#include <typeinfo>
#include <stdexcept>
namespace po = boost::program_options;
class any_option
{
public:
any_option() :
mContent(0) // no content
{}
template <typename T>
any_option(const T& value) :
mContent(new holder<T>(value))
{
// above is where the erasure happens,
// holder<T> inherits from our non-template
// base class, which will make virtual calls
// to the actual implementation; see below
}
any_option(const any_option& other) :
mContent(other.empty() ? 0 : other.mContent->clone())
{
// note we need an explicit clone method to copy,
// since with an erased type it's impossible
}
any_option& operator=(any_option other)
{
// copy-and-swap idiom is short and sweet
swap(*this, other);
return *this;
}
~any_option()
{
// delete our content when we're done
delete mContent;
}
bool empty() const
{
return !mContent;
}
friend void swap(any_option& first, any_option& second)
{
std::swap(first.mContent, second.mContent);
}
// now we define the interface we'd like to support through erasure:
// getting the data out if we know the type will be useful,
// just like boost::any. (defined as friend free-function)
template <typename T>
friend T* any_option_cast(any_option*);
// and the ability to query the type
const std::type_info& type() const
{
return mContent->type(); // call actual function
}
// we also want to be able to call options_description::add_option(),
// so we add a function that will do so (through a virtual call)
void add_option(po::options_description desc, const char* name)
{
mContent->add_option(desc, name); // call actual function
}
private:
// done with the interface, now we define the non-template base class,
// which has virtual functions where we need type-erased functionality
class placeholder
{
public:
virtual ~placeholder()
{
// allow deletion through base with virtual destructor
}
// the interface needed to support any_option operations:
// need to be able to clone the stored value
virtual placeholder* clone() const = 0;
// need to be able to test the stored type, for safe casts
virtual const std::type_info& type() const = 0;
// and need to be able to perform add_option with type info
virtual void add_option(po::options_description desc,
const char* name) = 0;
};
// and the template derived class, which will support the interface
template <typename T>
class holder : public placeholder
{
public:
holder(const T& value) :
mValue(value)
{}
// implement the required interface:
placeholder* clone() const
{
return new holder<T>(mValue);
}
const std::type_info& type() const
{
return typeid(mValue);
}
void add_option(po::options_description desc, const char* name)
{
desc.add_options()(name, po::value<T>(), "");
}
// finally, we have a direct value accessor
T& value()
{
return mValue;
}
private:
T mValue;
// noncopyable, use cloning interface
holder(const holder&);
holder& operator=(const holder&);
};
// finally, we store a pointer to the base class
placeholder* mContent;
};
class bad_any_option_cast :
public std::bad_cast
{
public:
const char* what() const throw()
{
return "bad_any_option_cast: failed conversion";
}
};
template <typename T>
T* any_option_cast(any_option* anyOption)
{
typedef any_option::holder<T> holder;
return anyOption.type() == typeid(T) ?
&static_cast<holder*>(anyOption.mContent)->value() : 0;
}
template <typename T>
const T* any_option_cast(const any_option* anyOption)
{
// none of the operations in non-const any_option_cast
// are mutating, so this is safe and simple (constness
// is restored to the return value automatically)
return any_option_cast<T>(const_cast<any_option*>(anyOption));
}
template <typename T>
T& any_option_cast(any_option& anyOption)
{
T* result = any_option_cast(&anyOption);
if (!result)
throw bad_any_option_cast();
return *result;
}
template <typename T>
const T& any_option_cast(const any_option& anyOption)
{
return any_option_cast<T>(const_cast<any_option&>(anyOption));
}
// NOTE: My casting operator has slightly different use than
// that of boost::any. Namely, it automatically returns a reference
// to the stored value, so you don't need to (and cannot) specify it.
// If you liked the old way, feel free to peek into their source.
#include <boost/foreach.hpp>
#include <map>
int main()
{
// (it's a good exercise to step through this with
// a debugger to see how it all comes together)
typedef std::map<std::string, any_option> map_type;
typedef map_type::value_type pair_type;
map_type m;
m.insert(std::make_pair("int", any_option(5)));
m.insert(std::make_pair("double", any_option(3.14)));
po::options_description desc;
BOOST_FOREACH(pair_type& pair, m)
{
pair.second.add_option(desc, pair.first.c_str());
}
// etc.
}
Let me know if something is unclear. :)
template<class T>
bool any_is(const boost::any& a)
{
try
{
boost::any_cast<const T&>(a);
return true;
}
catch(boost::bad_any_cast&)
{
return false;
}
}
// ...
po::options_description desc;
std::for_each(m_Config.getTuples().begin(),
m_Config.getTuples().end(),
[&desc](const TuplePair& _pair)
{
if(any_is<int>(_pair.first))
{
desc.add_options() { _pair.first, po::value<int>, ""};
}
else if(any_is<std::string>(_pair.first))
{
desc.add_options() { _pair.first, po::value<std::string>, ""};
}
else
{
// ...
}
});
// ...
If you have more than a handful of types consider using typelists.