std::cout.rdbuf() is so easy to use. But I wish to print string to console as well as write it to a file.
So what I am thinking of is to encapsulate two stream buffers into a derived class of std::streambuf, and pass this to rdbuf(). Is that possible?
How should I accomplish that?
I think a better way to do this would be to encapsulate two streams into an actual stream class derived from std::basic_ostream<...>.
Something for a start would be:
template<class charT, class traits = std::char_traits<charT>>
class basic_binary_stream : public std::basic_osteam<charT>
{
typedef std::basic_ostream<charT> stream_type;
typedef std::char_traits<charT> traits_type;
/* ... */
public:
binary_stream(stream_type& o1, stream_type& o2)
: s1(o1), s2(o2)
{ }
binary_stream& operator<<(int n)
{
s1 << n;
s2 << n;
return *this;
}
/* ... */
private:
stream_type& s1, &s2;
};
using binary_stream = basic_binary_stream<char>;
Related
I'm trying to find a more elegant solution for some code I'm working on at the moment. I have data that needs to be stored then moved around, but I don't really want to take up any more space than I need to for the data that is stored.
I have 2 solutions, but neither seem very nice.
Using inheritance and a tag
enum class data_type{
first, second, third
};
class data_base{
public:
virtual data_type type() const noexcept = 0;
};
using data_ptr = data_base*;
class first_data: public data_base{
public:
data_type type() const noexcept{return data_type::first;}
// hold the first data type
};
// ...
Then you pass around a data_ptr and cast it to the appropriate type.
I really don't like this approach because it requires upwards casting and using bare pointers.
Using a union and storing all data types
enum class data_type{
first, second, third
};
class data{
public:
data(data_type type_): type(type_){}
data_type type;
union{
// first, second and third data types stored
};
};
But I don't like this approach because then you start wasting a lot of memory when you have a large data type that may get passed around.
This data will then be passed onto a function that will parse it into a greater expression. Something like this:
class expression{/* ... */};
class expr_type0: public expression{/* ... */};
// every expression type
using expr_ptr = expression*;
// remember to 'delete'
expr_ptr get_expression(){
data_ptr dat = get_data();
// interpret data
// may call 'get_data()' many times
expr_ptr expr = new /* expr_type[0-n] */
delete dat;
return expr;
}
and the problem arrises again, but it doesn't matter in this case because the expr_ptr doesn't need to be reinterpreted and will have a simple virtual function call.
What is a more elegant method of tagging and passing around the data to another function?
It's difficult to envisage exactly what you're looking for without more information. But if I wanted some framework that allowed me to store and retrieve data in some structured way, in as-yet-unknown storage devices this is the kind of way I'd be thinking.
This may not be the answer you're looking for, but I think there'll be concepts here that will inspire you in the right direction.
#include <iostream>
#include <tuple>
#include <boost/variant.hpp>
#include <map>
// define some concepts
// bigfoo is a class that's expensive to copy - so lets give it a shared-handle idiom
struct bigfoo {
struct impl {
impl(std::string data) : _data(std::move(data)) {}
void write(std::ostream& os) const {
os << "I am a big object. Don't copy me: " << _data;
}
private:
std::string _data;
};
bigfoo(std::string data) : _impl { std::make_shared<impl>(std::move(data)) } {};
friend std::ostream& operator<<(std::ostream&os, const bigfoo& bf) {
bf._impl->write(os);
return os;
}
private:
std::shared_ptr<impl> _impl;
};
// all the data types our framework handles
using abstract_data_type = boost::variant<int, std::string, double, bigfoo>;
// defines the general properties of a data table store concept
template<class...Columns>
struct table_definition
{
using row_type = std::tuple<Columns...>;
};
// the concept of being able to store some type of table data on some kind of storage medium
template<class IoDevice, class TableDefinition>
struct table_implementation
{
using io_device_type = IoDevice;
using row_writer_type = typename io_device_type::row_writer_type;
template<class...Args> table_implementation(Args&...args)
: _io_device(std::forward<Args>(args)...)
{}
template<class...Args>
void add_row(Args&&...args) {
auto row_instance = _io_device.open_row();
set_row_args(row_instance,
std::make_tuple(std::forward<Args>(args)...),
std::index_sequence_for<Args...>());
row_instance.commit();
}
private:
template<class Tuple, size_t...Is>
void set_row_args(row_writer_type& row_writer, const Tuple& args, std::index_sequence<Is...>)
{
using expand = int[];
expand x { 0, (row_writer.set_value(Is, std::get<Is>(args)), 0)... };
(void)x; // mark expand as unused;
}
private:
io_device_type _io_device;
};
// model the concepts into a concrete specialisation
// this is a 'data store' implementation which simply stores data to stdout in a structured way
struct std_out_io
{
struct row_writer_type
{
void set_value(size_t column, abstract_data_type value) {
// roll on c++17 with it's much-anticipated try_emplace...
auto ifind = _values.find(column);
if (ifind == end(_values)) {
ifind = _values.emplace(column, std::move(value)).first;
}
else {
ifind->second = std::move(value);
}
}
void commit()
{
std::cout << "{" << std::endl;
auto sep = "\t";
for (auto& item : _values) {
std::cout << sep << item.first << "=" << item.second;
sep = ",\n\t";
}
std::cout << "\n}";
}
private:
std::map<size_t, abstract_data_type> _values; // some value mapped by ascending column number
};
row_writer_type open_row() {
return row_writer_type();
}
};
// this is a model of a 'data table' concept
using my_table = table_definition<int, std::string, double, bigfoo>;
// here is a test
auto main() -> int
{
auto data_store = table_implementation<std_out_io, my_table>( /* std_out_io has default constructor */);
data_store.add_row(1, "hello", 6.6, bigfoo("lots and lots of data"));
return 0;
}
expected output:
{
0=1,
1=hello,
2=6.6,
3=I am a big object. Don't copy me: lots and lots of data
}
Let's suppose originally I have the following design using CRTP:
template<class Outputter> class Generator {
protected:
vector<int> v;
private:
void work(ostream& out) {
// perform first part of some complex operations on v
out << *static_cast<Outputter *>(this);
// perform second part of some complex operations on v
out << *static_cast<Outputter *>(this);
// many more ....
// perform some final actions
}
public:
Generator(unsigned length): v(length) {}
friend ostream& operator<<(ostream& out, Outputter&& generator) {
// perform some preparation work
work(out);
// perform some final actions
return out;
}
};
class SimpleDumpOutputter : public Generator<SimpleDumpOutputter> {
private:
unsigned count;
public:
SimpleDumpOutputter(unsigned length): Generator(length), count() {}
friend ostream& operator<<(ostream& out, SimpleDumpOutputter& outputter) {
out << "Step " << ++count << " of calculation: "
copy(outputter.v.begin(), outputter.v.end(), ostream_iterator<int>(out, " "));
out << endl;
return out;
}
};
class FancyOutputter : public Generator<FancyOutputter> { // create a graph using graphviz's dot language to visualise v
private:
// abbreviated
public:
FancyOutputter(unsigned length): Generator(length) {}
friend ostream& operator<<(ostream& out, FancyOutputter& outputter) {
// write statements to out
return out;
}
};
// some more different Outputters, for example an Outputter that creates a pretty LaTeX document
In this design, there is a Generator CRTP class template that performs complex calculations on the vector<int> v and prints the result at each step/part of calculation using its derived classes's befriended operator<<.
Here's an interesting concept that I want to implement: I would want outputs in multiple formats in a single execution. Specifically, I thought I could do:
template<class Outputters> class AggregateOutputter : public Generator<AggregateOutputter<Outputters...> > {
private:
static const unsigned outputter_count = sizeof...(Outputters);
typedef array<ostream *, outputter_count> DestArr;
DestArr destinations;
public:
AggregateOutputter(unsigned v_length, DestArr destinations): IsomerGenerator<AggregateOutputter<Outputters...> >(length), destinations(destinations) {}
friend ostream& operator<<(ostream&, AggregateOutputter& outputter); // first argument is dummy, because we would use the ostreams in destinations
}
The idea is that the user would use, say, AggregateOutputter<SimpleDumpOutputter, FancyOutputter and construct the object with an array of two ostreams. Whenever Generator calls operator<< on the outputter class, the AggregateOutputter will iterate through the ostreams in destinations and the types in Outputters and invoke something along the lines of *dest_iter << *static_cast<Outputter_Iter>(this);.
I'm not sure how this would work though. I'm not sure whether multiple inheritance can be used this way, whether it is possible to "zip" between an array and a pack of parameterised types. Is anyone knowledgable in this situation?
I modified your original design. I thought Generator doing a bunch of calculations when the output operator is called is surprising to say the least. Also for your AggregateOutputter to output to ignore the ostream parameter of << is also surprising. Also, Outputter does not have an is-a relationship with Generator.
I tried to separate out the concerns, and ended up not using CRTP but using variadic templates, but I think it does what you want.
http://ideone.com/xQrnW4
#include <vector>
#include <iostream>
#include <iterator>
#include <array>
using namespace std;
class Generator {
protected:
vector<int> v;
public:
Generator(unsigned length): v(length) {}
template<class Outputter>
void do_calculations_with_output(Outputter& out){
// perform first part of some complex operations on v
out.output(v);
// perform second part of some complex operations on v
out.output(v);
// perform some final actions
}
};
class SimpleDumpOutputter {
private:
ostream* out;
unsigned count;
public:
SimpleDumpOutputter(ostream& os): out(&os), count() {}
template<class C>
void output(const C& c) {
*out << "Step " << ++count << " of calculation: ";
copy(c.begin(),c.end(), ostream_iterator<int>(*out, " "));
*out << endl;
}
};
class FancyOutputter {
ostream* out;
int count;
public:
FancyOutputter(ostream& os): out(&os),count() {}
template<class C>
void output(const C& c) {
// create a graph using graphviz's dot language to ease visualisation of v
*out << "Step " << ++count << " of calculation: ";
*out << "Graphviz output\n";
}
};
template<class... Outputters> class AggregateOutputter : private Outputters... {
private:
template<class First, class... Rest>
struct output_helper{
template<class C>
static void do_output(AggregateOutputter* pthis,const C& c){
static_cast<First*>(pthis)->output(c);
output_helper<Rest...>::do_output(pthis,c);
}
};
template<class First>
struct output_helper<First>{
template<class C>
static void do_output(AggregateOutputter* pthis,const C& c){
static_cast<First*>(pthis)->output(c);
}
};
public:
template<class... Out>
AggregateOutputter( Out&... out): Outputters(out)...{}
template<class C>
void output(const C& c) {
output_helper<Outputters...>::do_output(this,c);
}
};
int main(){
AggregateOutputter<FancyOutputter,SimpleDumpOutputter> out(cout,cout);
Generator g(10);
g.do_calculations_with_output(out);
}
Okay, here's a solution I came up with, after being inspired by John Bandela's solution here. (see my comment on the answer for why I don't think his approach fits my needs)
template<class... Outputters> class AggregateOutputter : public Generator<AggregateOutputter<Outputters...> > {
private:
typedef array<ostream *, sizeof...(Outputters)> DestArr;
DestArr destinations;
typedef typename DestArr::iterator DestArrIter;
struct OutputterHolder : public Outputters... {
OutputterHolder(vector<int>& v): Outputters(v)... {}
} outputter_holder;
template<class First, class... Rest> struct OutputHelper {
static void do_output(OutputterHolder *pthis, DestArrIter dest) {
**dest << *static_cast<First *>(pthis);
OutputHelper<Rest...>::do_output(pthis, ++dest);
}
};
template<class First> struct OutputHelper<First> {
static void do_output(OutputterHolder *pthis, DestArrIter dest) {
**dest << *static_cast<First *>(pthis);
}
};
public:
template<typename... OstreamStar> AggregateOutputter(unsigned length, OstreamStar... ostreams): Generator<AggregateOutputter<Outputters...> >(length), destinations{{ostreams...}}, outputter_holder(this->v) {
static_assert(sizeof...(OstreamStar) == sizeof...(Outputters), "number of outputters and destinations do not match");
}
friend ostream& operator<<(ostream& dummy_out, AggregateOutputter& outputter) {
OutputHelper<Outputters...>::do_output(&outputter.outputter_holder, outputter.destinations.begin());
// possibly write some logging info to dummy_out
return dummy_out;
}
};
// to use this:
ofstream fout("gv.gv");
cout << AggregateOutputter<FancyOutputter, SimpleDumpOutputter>(length, &fout, &cout);
The idea is that in addition to the output_helper in John's answer (which I have renamed to OutputHelper), there is another auxiliary struct called OutputterHolder, which inherits from all the Outputters. I've also used an array of ostream * to store the destination of output, and modified do_output to also take an iterator so that the correct ostream can be matched.
Importantly, to accompany the change, I've changed the protected member vector<int> v in Generator to a reference, ie vector<int>& v, so that the data structure in outputter_holder can be made to refer to the structure in AggregateOutputter instead. This also requires addition of another constructor in all outputters that takes vector<int>&. The original constructor that takes the length of v would now allocate the memory using new.
I'm not sure this solution I came up with is the best/most elegant solution though.
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));
I want to do something like the following code shows:
class foo
{
private:
std::fstream* m_stream;
public:
foo(std::fstream* stream) : m_stream(stream) { }
foo& write(char const* s, std::streamsize count)
{
if (/*condition*/)
{
m_stream->write(s, count);
}
else
{
// ...
}
return *this;
}
foo& read(char* s, std::streamsize count)
{
if (/*condition*/)
{
m_stream->read(s, count);
}
else
{
// ...
}
return *this;
}
};
I would need to add the same behavior to all similar methods (e.g. put). This shouldn't be applied to file streams only, but all other stream classes. Is there any easy way to allow these functionality?
Many of the formatted output operators (operator<<) write directly to the underlying stream buffer. What you need to do in order to accomplish this in a general fashion is derive a class from std::basic_streambuf that forwards all data to another std::basic_streambuf, and then optionally create a minimal std::basic_ostream implementation to make using your stream buffer easier.
I wouldn't say this is particularly easy, though, but it's the only way to do this in a way that can affect all stream types.
Here is an example of a minimal stream buffer that forwards to another stream buffer (and performs some meaningless transformation just to demonstrate what you can do), and an accompanying stream:
#include <iostream>
#include <streambuf>
template<typename CharType, typename Traits = std::char_traits<CharType> >
class ForwardingStreamBuf : public std::basic_streambuf<CharType, Traits>
{
public:
typedef Traits traits_type;
typedef typename traits_type::int_type int_type;
typedef typename traits_type::pos_type pos_type;
typedef typename traits_type::off_type off_type;
ForwardingStreamBuf(std::basic_streambuf<CharType, Traits> *baseStreamBuf)
: _baseStreamBuf(baseStreamBuf)
{
}
protected:
virtual int_type overflow(int_type c = traits_type::eof())
{
if( _baseStreamBuf == NULL )
return traits_type::eof();
if( traits_type::eq_int_type(c, traits_type::eof()) )
return traits_type::not_eof(c);
else
{
CharType ch = traits_type::to_char_type(c);
if( ch >= 'A' && ch <= 'z' )
ch++; // Do some meaningless transformation
return _baseStreamBuf->sputc(ch);
}
}
virtual int sync()
{
if( _baseStreamBuf == NULL )
return -1;
else
return _baseStreamBuf->pubsync();
}
private:
std::basic_streambuf<CharType, Traits> *_baseStreamBuf;
};
template<typename CharType, typename Traits = std::char_traits<CharType> >
class ForwardingStream : public std::basic_ostream<CharType, Traits>
{
public:
ForwardingStream(std::basic_ostream<CharType, Traits> &stream)
: std::basic_ostream<CharType, Traits>(NULL), _buffer(stream.rdbuf())
{
this->init(&_buffer);
}
ForwardingStreamBuf<CharType, Traits>* rdbuf() const
{
return &_buffer;
}
private:
ForwardingStreamBuf<CharType, Traits> _buffer;
};
This can be used very simply:
int main()
{
ForwardingStream<char> test(std::cout);
test << "Foo" << std::endl;
}
Which would output Gpp. I hope that helps you on your way.
Something like this?
template <class Stream>
class DecoratedStream {
public:
DecoratedStream(Stream* stream) : m_stream(stream) {}
DecoratedStream& write(const char* data, int count) {
m_stream->write(data, count);
}
};
If I understand you correctly, you want to decorate methods of any iostream. So just make your decorator take an iostream as decoratee (as opposed to an fstream, which is a subclass of iostream).
Having pointer inside a structure as your current approach is dangerous and error prone. Instead just derive such stream classes and implement basic constructors and wrap around your custom methods such as write().
template<typename StreamType>
class foo : StreamType
{
// wrapper constructors supporting StreamType() constructors
foo& write(char const* s, std::streamsize count)
{
//...
return *this;
}
};
Usage:
foo<fstream> obj;
obj.write(...);
The usual solution for this sort of problem is to use templates. There
aren't that many functions in an std::istream or and std::ostream
which need covering, and a good template member for<<and>>should
cover a lot of the cases. In most of the cases I've done this, I've
only offerred<<or>>`. (Generally speaking, I've not needed
bidirectional streams.)
As for handling other types of streams, just use std::iostream instead
of std::fstream. (In general, except when opening files, you
shouldn't see the fstream part.)
I'm looking at making a logging class which has members like Info, Error etc that can configurably output to console, file, or to nowhere.
For efficiency, I would like to avoid the overhead of formatting messages that are going to be thrown away (ie info messages when not running in a verbose mode). If I implement a custom std::streambuf that outputs to nowhere, I imagine that the std::ostream layer will still do all the formatting. Can anyone suggest a way to have a truly "null" std::ostream that avoids doing any work at all on the parameters passed to it with <<?
A swift google came up with this example which may be of use. I offer no guarantees, except that it compiles and runs :-)
#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;
int main() {
onullstream os;
os << 666;
}
all, thanks for sharing the code, I just do a test, then Neil's method will still do the string formating, for example:
#include <streambuf>
#include <ostream>
#include <iostream>
using namespace std;
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;
class MyClass
{
int a;
friend ostream& operator<< (ostream&, MyClass const&);
};
ostream& operator<<(ostream& out,MyClass const& b)
{
std::cout<<"call format function!!";
out << b.a;
return out;
}
int main() {
onullstream os;
MyClass obj;
os<<obj;
}
Running this program, you will find that "ostream& operator<<(ostream& out,MyClass const& b)" will be called. So, doing format on the obj will still be called. So, we still can't avoid the overhead of formatting messages.
To prevent the operator<<() invocations from doing formatting, you should know the streamtype at compile-time. This can be done either with macros or with templates.
My template solution follows.
class NullStream {
public:
void setFile() { /* no-op */ }
template<typename TPrintable>
NullStream& operator<<(TPrintable const&)
{ return *this; } /* no-op */
}
template<class TErrorStream> // add TInfoStream etc
class Logger {
public:
TErrorStream& errorStream() {
return m_errorStream;
}
private:
TErrorStream m_errorStream;
};
//usage
int main() {
Logger<std::ofstream> normal_logger; // does real output
normal_logger.errorStream().open("out.txt");
normal_logger.errorStream() << "My age is " << 19;
Logger<NullStream> null_logger; // does zero output with zero overhead
null_logger.errorStream().open("out.txt"); // no-op
null_logger.errorStream() << "My age is " << 19; // no-op
}
Since you have to do this at compile-time, it is of course quite inflexible.
For example, you cannot decide the logging level at runtime from a configuration file.
Probably you'll need more than just text formatting and message filtering. What about multithreading?
I would implement the filtering and multithreading synchronization as the responsibility of a separate class.
However, logging is a not-so-simple problem, and I would try to use existing logging solutions, instead of developing a new one.
Why not using existing logging solutions used by millions of users?
log4j, log4net, log4cxx.., to name just a few..