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 );
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.
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 implementtemplate <typename... Args> void print(Args&&... args) simple_print(std::forward<Args>(args)...);
.– user2709407
Aug 31 at 1:02