Say I have an employee object with the following data members:
class Employee {
private:
int _id;
std::string _name;
std::string _address;
std::string _city;
std::string _state;
std::string _country;
std::string _phone;
double _salary;
...
}
I would like to output it two different ways:
XML
<Employee>
<id>12345</id>
<name>Jack Dough</name>
<address>24437 Princeton</address>
<city>Dearborn</city>
<state>Michigan</state>
<country>USA</country>
<phone>303-427-0153</phone>
<salary>140000</salary>
</Employee>
and JSON-like:
id: 12345
name: Jack Dough
address: 24437 Princeton
city: Dearborn
state: Michigan
country: USA
phone: 303-427-0153
salary: 140000
How would I be able to do so with stream manipulators? For Example:
Employee* employee = new Employee(12345, "Jack Dough", "24437 Princeton", "Dearborn", "Michigan", "USA", "303-427-0153", 140000.00);
cout << toXML << employee;
cout << toJSON << employee;
First of all, unless you really need to implement this as a separate manipulator, consider other routes. Two obvious possibilities would be a custom locale, or just a function that does the formatting and returns the result as a string. The former would look something like:
std::locale myLoc(std::locale(), XML_formatter);
cout.imbue(myLoc);
cout << employee;
This makes the formatting style persistent for the stream in general. If you really need to mix different styles in the same stream, the function version is a lot simpler:
std::string toXML(Employee const &e) {
std::stringstream ret;
ret << "Employee>\n<id>" << id << "</id>"
<< // ...
return ret.str();
}
// ...
cout << toXML(employees[i]);
If you truly have no choice but to implement this as a separate manipulator, you'll need to store a flag to indicate the current format in the stream. Streams provide a memory management interface in the form of xalloc
, iword
and pword
. Basically, xalloc
allocates one word for you. iword
gives you access to that word as a reference to a long, and pword
gives you access to it as a reference to pointer to void. In your case, you apparently only need one or two bits, so you probably want to use iword
and define a couple of bits to specify the formatting for the type. Your toXML
and toJSON
manipulators will set the appropriate bits, and your operator<<
will read them to control its behavior. It's clumsy and ugly, but it does work if you're willing to put a little effort into it.