implement STL pretty printing using Boost HOF

implement STL pretty printing using Boost HOF



pretty print container of arbitrary type



The following code of few lines provides same output as prettyprint.hpp in question,
but the output stream is limited to std::cout.


std::cout



How to rewrite those code using boost::hof to provide print(std::ostream&, ...) like interface?


boost::hof


print(std::ostream&, ...)


#include <iostream>
#include <boost/hof.hpp>

BOOST_HOF_STATIC_LAMBDA_FUNCTION(simple_print) = //boost::hof::proj(
boost::hof::fix(boost::hof::first_of(
(auto, const auto& x) -> decltype(std::cout << x, void())
std::cout << x;
,
(auto self, const auto& range)
-> decltype(self(*std::begin(range)), void())
bool sep = false;
std::cout << '';
for (const auto& x : range)
if (sep)
std::cout << ',';
else
sep = true;
self(x);

std::cout << '';
,
(auto self, const auto& tuple)
using namespace boost::hof;
std::cout << '(';
bool sep = false;
unpack(proj([&](const auto& i)
if (sep)
std::cout << ',';
else
sep = true;
self(i);
))(tuple);
std::cout << ')';
));//})));

template <typename... Args>
void print(Args&&... args)
simple_print(std::make_tuple(std::forward<Args>(args)...));



//---- user code ---
struct XX
int n = 0;

friend std::ostream& operator<<(std::ostream& os, const XX& o)
return os << o.n << "XX";

;

int main()

std::vector v = 1, 2, 3, 4;
std::map<std::string, int> m = "a", 30, "bb", 31, "ccc", 32;

auto t = std::make_tuple(6, 7, 8, 9);
auto t2 = std::make_tuple(11, std::ref(v), t);
auto t3 = std::make_tuple(t2, std::vector1234, 23, 2, 3, 3, "abc",
std::vector
std::vector11, 12, 13, std::vector15, 16, 17, std::vector19);
print(t3, "xxxx", 55, m, std::vector<std::string>"x", XX66);
// (((11, [1, 2, 3, 4], (6, 7, 8, 9)), [1234, 23, 2, 3, 3], abc, [[11, 12,
// 13], [15, 16, 17], [19]]), xxxx, 55, [(a, 30), (bb, 31), (ccc, 32)], [x],
// 66XX)




1 Answer
1



Just adding a parameter to pass the ostream would suffice:


BOOST_HOF_STATIC_LAMBDA_FUNCTION(simple_print_ex) = boost::hof::fix(
boost::hof::first_of(
(auto, auto& os, const auto &x) -> decltype(os << x, void()) os << x; ,
(auto self, auto& os, const auto &range) -> decltype(self(os, *std::begin(range)), void())
bool sep = false;
os << '';
for (const auto &x : range)
os << '';
,
(auto self, auto& os, const auto &tuple)
using namespace boost::hof;
os << '(';
bool sep = false;
unpack(proj([&](const auto &i)
sep = !sep ))(tuple);
os << ')';
));

template <typename Ostream, typename... Args> void print_ex(Ostream& os, Args &&... args) simple_print_ex(os, std::make_tuple(std::forward<Args>(args)...));



Now you can use it like so:



Live On Wandbox


std::ofstream ofs("test.txt");
print_ex(ofs, t3, "xxxx", 55, m, std::vector<std::string> "x" , XX 66 );
ofs << "n";



Of course, the old print can be a trivial forwarding wrapper now:


print


template <typename... Args> void print(Args &&... args)
print_ex(std::cout, std::forward<Args>(args)...);



Live On Wandbox


#include <boost/hof.hpp>
#include <iostream>

BOOST_HOF_STATIC_LAMBDA_FUNCTION(simple_print_ex) = boost::hof::fix(
boost::hof::first_of(
(auto, auto& os, const auto &x) -> decltype(os << x, void()) os << x; ,
(auto self, auto& os, const auto &range) -> decltype(self(os, *std::begin(range)), void())
bool sep = false;
os << '';
for (const auto &x : range)
os << '';
,
(auto self, auto& os, const auto &tuple)
using namespace boost::hof;
os << '(';
bool sep = false;
unpack(proj([&](const auto &i)
sep = !sep ))(tuple);
os << ')';
));

template <typename Ostream, typename... Args> void print_ex(Ostream& os, Args &&... args) simple_print_ex(os, std::make_tuple(std::forward<Args>(args)...));
template <typename... Args> void print(Args &&... args) print_ex(std::cout, std::forward<Args>(args)...);

//---- user code ---
struct XX
int n = 0;

friend std::ostream &operator<<(std::ostream &os, const XX &o) return os << o.n << "XX";
;

#include <map>
#include <vector>
#include <fstream>
int main()
using namespace std::string_literals;

std::vector v = 1, 2, 3, 4 ;
std::map m std::pair "a"s, 30 , "bb", 31 , "ccc", 32 ;

auto t = std::make_tuple(6, 7, 8, 9);
auto t2 = std::make_tuple(11, std::ref(v), t);
auto t3 = std::make_tuple(t2, std::vector 1234, 23, 2, 3, 3 , "abc",
std::vector std::vector 11, 12, 13 , std::vector 15, 16, 17 , std::vector 19 );
std::ofstream ofs("test.txt");
print_ex(ofs, t3, "xxxx", 55, m, std::vector<std::string> "x" , XX 66 );
ofs << "n";

print(t3, "xxxx", 55, m, std::vector<std::string> "x" , XX 66 );





Thanks for your answer. With your code I figured out what stop me adding the Ostream param was the first boost::hof::proj aiming to implement template <typename... Args> void print(Args&&... args) simple_print(std::forward<Args>(args)...); .
– user2709407
Aug 31 at 1:02


boost::hof::proj


template <typename... Args> void print(Args&&... args) simple_print(std::forward<Args>(args)...);



Required, but never shown



Required, but never shown






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

𛂒𛀶,𛀽𛀑𛂀𛃧𛂓𛀙𛃆𛃑𛃷𛂟𛁡𛀢𛀟𛁤𛂽𛁕𛁪𛂟𛂯,𛁞𛂧𛀴𛁄𛁠𛁼𛂿𛀤 𛂘,𛁺𛂾𛃭𛃭𛃵𛀺,𛂣𛃍𛂖𛃶 𛀸𛃀𛂖𛁶𛁏𛁚 𛂢𛂞 𛁰𛂆𛀔,𛁸𛀽𛁓𛃋𛂇𛃧𛀧𛃣𛂐𛃇,𛂂𛃻𛃲𛁬𛃞𛀧𛃃𛀅 𛂭𛁠𛁡𛃇𛀷𛃓𛁥,𛁙𛁘𛁞𛃸𛁸𛃣𛁜,𛂛,𛃿,𛁯𛂘𛂌𛃛𛁱𛃌𛂈𛂇 𛁊𛃲,𛀕𛃴𛀜 𛀶𛂆𛀶𛃟𛂉𛀣,𛂐𛁞𛁾 𛁷𛂑𛁳𛂯𛀬𛃅,𛃶𛁼

Edmonton

Crossroads (UK TV series)