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.