I have an object that I want to be able to stream. But I want to be able to stream it in different ways by using different formats, or should I say ways to describe this object. And I wonder how this is supposed to be solved with streams.
What I want is to be able to use a generic format and use some kind of format adapter to transform the generic format into the preferred format.
I also want to be able to separate the format from the implementation of Item, so I do not have to change Item each time a new format is added or changed.
this code illustrate approximately what I want.
Item item;
std::cout << "generic formatted:" << item;
std::cout << "custom formatted:" << CustomItemFormat() << item;
but this might not be possible or practical.
how is the streaming library intended to be used facing such problems?
Personally I would write a set of formatters.
The formatters have to know the internals of the object they are formatting
but making them friends should not be a big deal.
class X
{ friend std::ostream& operator<<(std::ostream& str,XML_Format const& formatter);
friend std::ostream& operator<<(std::ostream& str,Json_Format const& formatter);
friend std::ostream& operator<<(std::ostream& str,Fred_Format const& formatter);
public: int value() const {return 5;}
};
struct XML__Foram { X const& print; XML_Format(X const& v): print(v) {} };
struct Json_Format { X const& print; Json_Format(X const& v): print(v) {} };
struct Fred_Format { X const& print; Fred_Format(X const& v): print(v) {} };
std::ostream& operator<<(std::ostream& str,XML_Format const& formatter)
{
return str << "<XObj>" << formatter.print.value() << "</XObj>";
}
std::ostream& operator<<(std::ostream& str,Json_Format const& formatter)
{
return str << "{XObj:{" << formatter.print.value() << "}}";
}
std::ostream& operator<<(std::ostream& str,Fred_Format const& formatter)
{
return str << "Killl Kill Kill. Friday 13th";
}
int main()
{
X obj;
std::cout << XML_Format(obj) << std::endl;
}
Yes it's possible, the magic word you're looking for is stream manipulators.
Check out this question: C++ custom stream manipulator that changes next item on stream
You need to write a stream manipulator which stores information in the stream that is then used by operator<<(std::ostream&,const Item&). See the beginning of this answer for how to store user data in a stream.
IOStreams are not very well-suited for this, but you can use a formatting library such as {fmt} that provides better extensibility. For example:
struct Item {
int value;
};
template <>
struct fmt::formatter<Item> {
enum format { generic, custom };
format f = generic;
constexpr auto parse(parse_context &ctx) {
auto it = ctx.begin(), end = ctx.end();
if (it == end) return it;
if (*it == 'g') f = generic;
else if (*it == 'c') f = custom;
else return it;
return ++it;
}
template <typename FormatContext>
auto format(const Item& item, FormatContext &ctx) {
return format_to(ctx.out(), f == generic ? "{}" : "{:x}", item.value);
}
};
Then you can use Item objects with any formatting function such as print:
fmt::print("{}", Item{42}); // Default generic format - value formatted as decimal
fmt::print("{:g}", Item{42}); // Explicit generic format
fmt::print("{:c}", Item{42}); // Custom format - value formatted as hex
Disclaimer: I'm the author of {fmt}.
What is so bad about Item.CustomItemFormat()?
Alternatively there are some design patterns aimed at solving this problem, namely the visitor pattern.
You could also have CustomItemFormat(Item)?
I dont think that asking streams to solve this problem is the right orientation, you should delegate the task of showing itself to the Item class
The more I think about it I am starting to wonder if I am approaching this the wrong way. Perhaps I should have a generic format interface and setting the format for the item, so the item can output itself using this format.
Does this make sense?
Try using the Visitor design pattern:
struct Object_Writer_Interface
{
virtual void write_member_i(int value) = 0;
virtual void write_member_c(char value) = 0;
};
struct Object
{
int i;
char c;
void write(Object_Writer_Interface * p_writer)
{
if (p_writer)
{
p_writer->write_member_i(i);
p_writer->write_member_c(c);
}
}
};
struct Stream_Object_Writer
: public Object_Writer_Interface
{
Stream_Object_Writer(std::ostream& out)
: m_out(out)
{ ; }
void write_member_i(int value)
{
m_out << i << '\n';
}
void write_member_c(char c)
{
m_out << "'" << c << "'\n";
}
std::ostream& m_out;
};
int main(void)
{
Object o;
o.i = 5;
o.c = 'M';
// Create a writer for std::cout
Stream_Object_Writer writer(std::cout);
// Write the object to std::cout using the writer
o.write(&writer);
return EXIT_SUCCESS;
}
With this design, to write the objects to a socket, you derive a class from Object_Writer_Interface to handle the socket. And similarly if you want to serialize the Object.
I'm currently using this technique for writing objects to GUI list boxes, database records and Xml files. Unlike the technique for overloading operator <<, I didn't have to modify the principle class when developing new Writers.
Related
The relevant code is :
std::fstream fout("Logs.txt");
class Logs;
typedef std::ostream& (*ostream_manipulator2)(std::ostream&);
class LogsOutput
{
public:
LogsOutput() {}
~LogsOutput() {}
Logs * pLogs;
friend LogsOutput& operator<<(LogsOutput &logsClass, std::string &strArg);
friend LogsOutput& operator<<(LogsOutput &logsClass, const char *strArg);
friend LogsOutput& operator<<(LogsOutput &logsClass, ostream_manipulator2 pf);
friend LogsOutput& operator<<(LogsOutput &logsClass, uint64_t number);
};
LogsOutput *pLogsOutput;
template <typename T>
T& LOUToutput()
{
if (pLogsOutput)
{
return (*pLogsOutput);
}
else
return fout;
}
I would like to call this function as such :
LOUToutput () << "Print this line " << std::endl;
Sometimes however the LogsOutput class isn't created, therefore dereferencing its pointer would crash in which case i would rather output to file instead.
I understand that the compiler cannot tell at compile time whether the LogsOutput class will be instantiated or not and thus cannot deduce the type of the template, but I don't see any other way I could make it work.
So my question is how can my function return a different type based on a run time condition ?
The complex solution to this is to use inheritance. If you were to inherit from std::ostream, you could return a common base class (Here is a discussion if you are interested: How to inherit from std::ostream?)
The simpler solution, imo., is to return a proxy class that redirects output as necessary.
struct LogProxy {
LogsOutput *pLog;
// ...
LogProxy &operator<<(std::string &o) {
if(pLogsOutput) {
*pLog << o;
} else {
// Assuming this is available as a global.. You probably don't want to do that
fout << o;
}
return *this;
}
// ....
};
LogProxy LOUToutput() {
return LogProxy { pLogsOutput; };
}
A few other general comments:
If you want to use templates you would need to make this a compile time condition. You could use something like std::enable_if<> to provide multiple template overloads of LOUToutput() which choose at compile time where to log to.
I'm guessing it was just for the purposes of posting to SO, but your code has multiple globals declared in a header file. You'll need to fix that.
There are no const declarations on your code. A lot of those operators look like they should at least be declared const on their output (string,.etc.) parameters.
EDIT: Here is a working (compiles correctly) sample of this idea:
#include <iostream>
struct PRXY {
bool cond;
const PRXY &operator<<(const std::string &t) const {
if(cond) {
std::cout << t;
} else {
std::cerr << t;
}
return *this;
}
};
PRXY pr(bool cond) {
return PRXY { cond };
}
void test() {
pr(false) << "Hello";
}
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.
How to implement ostream-like class from scratch using printf only?
For me looks like the problem is in choosing the format string ,which is actually equal to the identifying input`s type and treating precision
I assume you mean something that overloads operator<< by "an ostream-like class". It's easy to identify the type of the argument to a function just by having overloads. For example, you might have:
ostreamlike& ostreamlike::operator<<(int x)
{
printf("%d", x);
return *this;
}
ostreamlike& ostreamlike::operator<<(float x)
{
printf("%f", x);
return *this;
}
The format of the output is determined by whichever overload is picked.
Think, it could be something like that
#include <stdio.h>
class ostreamlike {
public:
ostreamlike(FILE* f_): f(f_) {}
ostreamlike& write(int n) {
fprintf(f, "%d", n);
return *this;
}
ostreamlike& write(const char* n) {
fprintf(f, "%s", n);
return *this;
}
private:
FILE* f;
};
// operator for types that is supported ostreamlike internally
template <typename type>
ostreamlike& operator<<(ostreamlike& stream, const type& data) {
return stream.write(data);
}
// external implementations to write using ostreamlike
ostreamlike& operator<<(ostreamlike& stream, bool data) {
return stream.write(data ? "true" : "false");
}
int main() {
ostreamlike s(stdout);
s << "hello " << 1 << " : " << true << "\n";
return 0;
}
It depends on how close to the real ostream you want to be. Assuming you want to do it properly you would also need a streambuf derived class. ostream only does the formatting, the actual I/O is done by an internal streambuf derived class. Since streambuf does unformatted I/O you would need to use fwrite not printf.
If your goal is just to do I/O on an already existing FILE* pointer this is the way to go. You derive one class from streambuf, say streambuf_with_FILE and then you derive another class from ostream say ostream_with_FILE. streambuf_with_FILE overrides the appropriate methods to do the actual I/O and ostream_with_FILE has an internal streambuf_with_FILE object. There's actually very little code required.
For an API that I am working on, I want to allow the user to insert custom objects into an ostream, but these objects have no meaning on their own, and are too memory constrained to include an additional pointer or reference for context. (Think tens of millions of 16-/32-/48-bit objects in an embedded system with limited memory.)
Suppose the user initializes the underlying context, and looks up one of these objects:
DDB ddb("xc5vlx330t");
Tilewire tw = ddb.lookUpTilewire("DSP_X34Y0", "DSP_IMUX_B5_3");
...
std::cout << complexDataStructure;
In an entirely different scope, possibly nested far away from the user's explicit code, we may need to insert the object into an ostream, with ddb unavailable.
os << tw;
The actual value encapsulated by tw is 97,594,974, but the desired output is this:
DSP_IMUX_B5_3#[263,84] DSP "DSP_X34Y0" (1488#77406)
In order for this to work, the appropriate insertion operator would need access to ddb, but it cannot rely on static or global variables or functions (for multithreading reasons). What I'd like to do is allow the user to request and use a stream wrapper kind of like this:
ostream& wrappedCout = ddb.getWrappedOstream(std::cout);
The returned subclass of ostream would include a reference to ddb for use by special stream inserters that needed it, and a reference to the original stream—std::cout in this case—where it would forward all of its output.
Unfortunately, the inheritance or composition schemes that I have come up with are messy to code up (not an enormous concern), and possibly problematic for the user (a much larger concern). Any suggestions on how to elegantly make ddb available to insertion operators? I am marginally aware of boost.Iostreams, but not sure that it will help me out here.
Write a custom stream manipulator that stores a reference to ddb using the iword/pword mechanism. Here is an example, you'd need to add locking around the iwork_indexes map in a multithreaded program.
class dbb
{
public:
explicit dbb(int value) : m_value(value) {}
int value() const { return m_value; }
private:
int m_value;
};
class dbb_reliant_type
{
public:
dbb_reliant_type(const std::string& value) : m_value(value) {}
const std::string& value() const { return m_value; }
private:
std::string m_value;
};
typedef std::map<std::ostream*, int> iword_map;
iword_map iword_indexes;
inline int get_iword_index(std::ostream& os)
{
iword_map::const_iterator index = iword_indexes.find(&os);
if(index == iword_indexes.end())
{
std::pair<iword_map::iterator, bool> inserted = iword_indexes.insert(std::make_pair(&os, os.xalloc()));
index = inserted.first;
}
return index->second;
}
inline std::ostream& operator<<(std::ostream& os, const dbb& value)
{
const int index = get_iword_index(os);
if(os.pword(index) == 0)
os.pword(index) = &const_cast<dbb&>(value);
return os;
}
std::ostream& operator<<(std::ostream& os, const dbb_reliant_type& value)
{
const int index = get_iword_index(os);
dbb* deebeebee = reinterpret_cast<dbb*>(os.pword(index));
os << value.value() << "(" << deebeebee->value() << ")";
return os;
}
int main(int, char**)
{
dbb deebeebee(5);
dbb_reliant_type variable("blah");
std::cout << deebeebee << variable << std::endl;
return 0;
}
I'm not entirely sure if I understand what can be accessed at what time and what can and can't change, but....can you do something like this
struct TilewireFormatter {
DDB *ddb;
TilewireFormatter(DDB* d) : ddb(d) {}
print(std::ostream& out, const Tilewire& obj) {
// some formatting dependent on ddb
out << obj;
}
};
and replace out << tw; with formatter.print(out, tw);
then not provide any sort of << operator overload for Tilewire and pass an instance of TilewireFormatter around that's used to format them based on what ddb is?
I'm new at this, so in case providing my own answer gets in the way of me sharing the credit with Gary, well, Gary pointed out what I had just stumbled upon moments before through the same reference: Stream Storage for Private Use: iword, pword, and xalloc
#include <iostream>
// statically request a storage spot that can be associated with any stream
const int iosDdbIndex = std::ios_base::xalloc();
class DDB {
public:
// give the stream a pointer to ourselves
void bless(std::ostream& os) { os.pword(iosDdbIndex) = this; }
// provide a function that the insertion operator can access
int getSomething(void) { return 50; }
};
class Tilewire {
friend std::ostream& operator<< (std::ostream& os, Tilewire tilewire);
// encapsulate a dummy value
int m;
public:
// construct the Tilewire
Tilewire(int m) : m(m) {}
};
std::ostream& operator<< (std::ostream& os, Tilewire tilewire) {
// look up the pointer to the DDB object
DDB* ddbPtr = (DDB*) os.pword(iosDdbIndex);
// insert normally, and prove that we can access the DDB object's methods
return os << "Tilewire(" << tilewire.m << ") with DDB param " << ddbPtr->getSomething();
}
int main (int argc, char * const argv[]) {
DDB ddb;
ddb.bless(std::cout);
std::cout << Tilewire(0) << std::endl;
return 0;
}
Rather than fudging around and trying to find a way to pass contextual information while using the insertion operator, I suggest you make something like a print method like choobablue suggests. It's a nice and simple solution and anything fancier is probably more trouble than it's worth.
I also find it odd that you choose iostreams for an embedded system. They're one of the most bloated parts of the C++ standard library (not just by implementation, but by design) and if you are working on an embedded system, you could just as well roll your own alternative of this (still based on the basic design of iostreams) and can probably do it just as quickly as trying to use iostream effectively and across multiple threads.
I'm trying to create an Enum that has a string label and a value and I plan to use this to read stuff from an ini file.
For example in the ini file I might have some double, int or string type values preceded by the tag/name of the value:
SomeFloat = 0.5
SomeInteger = 5
FileName = ../Data/xor.csv
When I read the tag from a file it comes in as a string, so I'd just like to have std::set that keeps all of my values... when I read the tag I can just compare it against the EnumType and if matches the label then I will check the type and do the proper conversion (atoi or just use the string, etc.)
For example:
EnumType<int> someInteger;
someInteger.label = "SomeInteger";
someInteger.type = INT;
std::set<EnumType> myValues;
//
// populate the set
myValues.insert(someInteger);
//
void ProcessTagAndValue(const std::string &tag, const std::string &value)
{
switch(myValues[tag].type)
{
case INT:
myValues[tag].value = atoi(value);
break;
case DOUBLE:
//
break;
case STRING:
myValues[tag].value = value;
break;
default:
break;
}
}
enum ValueType{INT,DOUBLE,STRING];
template <class T>
struct EnumType{
std::string label;
ValueType type;
T value;
bool operator==(const EnumType &other) const {
return this->label == other.label;
}
bool operator==(const T& other ) const
{
return this->value == other;
}
T& operator=(const T& p)
{
value = p;
return value;
}
EnumType& operator=(const EnumType& p)
{
if (this != &p) { // make sure not same object
this->label = p.label;
this->value = p.value;
}
return *this;
}
};
I have several questions:
Can you guys tell me any better solutions? I'm not sure if I'm trying to be too clever for my own good, or if this is really a viable solution.
If my solution is acceptable, then can anybody tell me how I can declare a set of std::set<EnumType<...>> so that it can accept any type (int, double, string) without me actually knowing which type the enum is going to be using for the value?
If you have any code, then it would be GREAT! :)
If you have limited and very stable set of types, then Boost.Variant may be used.
If you going to add support for new types later, then better forget about this method. In this situation solution, based on Boost.Any, or pair of strings will be better.
typedef boost::variant<int, double, std::string> ValueType;
struct EnumType {
std::string label;
ValueType value;
};
Another question is: "How these values will be used later?" If you are going to pass "SomeInteger" to function, accepting int, you still have to run code similar to:
acceptInt( get<int>( v.value ) ); // get may throw
This approach works better when you have uniform processing of fixed set of types:
class processValue : public boost::static_visitor<>
{
public:
void operator()(int i) const
{
acceptInt( i );
}
void operator()(double d) const
{
acceptDouble( d );
}
void operator()(const std::string & str) const
{
acceptString( str );
}
};
boost::apply_visitor( processValue(), v.value );
Have you looked at Boost.Any? It should do what you want (and if you need to roll your own, you can peek at the source for hints).