Достаточно добавить параметр для передачи ostream:
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) {
sep = !sep || os << ',';
self(os, x);
}
os << '}';
},
[](auto self, auto& os, const auto &tuple) {
using namespace boost::hof;
os << '(';
bool sep = false;
unpack(proj([&](const auto &i) {
sep = !sep || os << ',';
self(os, i);
}))(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)...)); }
Теперь вы можете использовать его так:
Live On Wandbox
std::ofstream ofs("test.txt");
print_ex(ofs, t3, "xxxx", 55, m, std::vector<std::string>{ "x" }, XX{ 66 });
ofs << "\n";
Конечно, старый 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) {
sep = !sep || os << ',';
self(os, x);
}
os << '}';
},
[](auto self, auto& os, const auto &tuple) {
using namespace boost::hof;
os << '(';
bool sep = false;
unpack(proj([&](const auto &i) {
sep = !sep || os << ',';
self(os, i);
}))(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 });
}