Najprostszy sposób, że nasuwa się rozpocząć, tworząc rodzaj znacznika i podaje się jedną instancję:
struct JsonStreamTag {} json;
pozwól Taki znacznik skonstruowania obiektu zawijany strumień:
class JsonStream {
public:
// (1)
friend JsonStream operator<<(std::ostream& ostream, const JsonStreamTag&) {
return JsonStream(ostream);
}
// (2)
template<class T>
friend JsonStream& operator<<(JsonStream& json_stream, const T& value) {
write_json(json_stream.ostream, value); // (3)
return json_stream;
}
protected:
JsonStream(std::ostream& ostream) : ostream(ostream) {}
private:
std::ostream& ostream;
};
Konstruktor to protected
, aby zapewnić, że można użyć tylko some_ostream << json
(1) do skonstruowania JsonStream
. Drugi operator wstawiania (2) wykonuje faktyczne formatowanie. Następnie należy zdefiniować przeciążenie write_json()
(3) dla każdego odpowiedniego typu:
void write_json(std::ostream& stream, int value) {
stream << value;
}
void write_json(std::ostream& stream, std::string value) {
stream << '"' << escape_json(value) << '"';
}
// Overloads for double, std::vector, std::map, &c.
Alternatywnie pominąć (2) i dodać przeciążenia dla operator<<(JsonStream&, T)
zamiast.
Następnie wystarczy wykonać ten sam proces, aby zapisać odpowiednie XmlStream
przy użyciu XmlStreamTag
i write_xml()
. Zakłada to, że twoje dane wyjściowe mogą być zbudowane całkowicie z określonych wartości, które piszesz; jeśli potrzebujesz nagłówek lub stopkę, która jest taka sama we wszystkich plików będziesz pisać, wystarczy użyć konstruktora i destruktora:
XmlStream(std::ostream& ostream) : ostream(ostream) {
ostream << "<?xml version=\"1.0\"?><my_document>"
}
~XmlStream() {
ostream << "</my_document>";
}
Nie sądzę, że jest to bardzo dobry pomysł. Nie działa dla rzeczy takich jak 'out << json <<" Header: "<< obj;' na przykład. (Oczywiście, dla czegoś takiego jak XML, i tak nie miałoby to sensu, ale to jest argument za niestosowaniem manipulatorów.) –
@JamesKanze: Pytanie nie jest jasno zdefiniowane. Aby dosłownie odpowiedzieć na pytanie, założyłem, że "strumień JSON" traktowałby wszystko jako wartość JSON. Ale myślę, że takie coś jest nie na miejscu. –
XML (i JSON, o ile mi wiadomo) nie są strumieniami; są to bardziej złożone struktury. Niezwiązany typ nie powinien wyprowadzać XML lub JSON do 'ostream'; powinien wstawić go do jakiegoś wystąpienia struktury danych XML lub JSON, która następnie zajmie się strumieniowym wyjściem, na poziomie pliku. –