1// Copyright 2016-2024 Antony Polukhin
2
3// Distributed under the Boost Software License, Version 1.0.
4// (See the accompanying file LICENSE_1_0.txt
5// or a copy at <http://www.boost.org/LICENSE_1_0.txt>.)
6
7//[pfr_sample_printing
8/*`
9 The following example shows how to write your own io-manipulator for printing:
10*/
11#include <boost/pfr/ops.hpp>
12#include <ostream>
13
14namespace my_ns {
15
16/// Usage:
17/// struct foo {std::uint8_t a, b;};
18/// ...
19/// std::cout << my_ns::my_io(foo{42, 22});
20///
21/// Output: 42, 22
22template <class T>
23auto my_io(const T& value);
24
25namespace detail {
26 // Helpers to print individual values
27 template <class T>
28 void print_each(std::ostream& out, const T& v) { out << v; }
29 void print_each(std::ostream& out, std::uint8_t v) { out << static_cast<unsigned>(v); }
30 void print_each(std::ostream& out, std::int8_t v) { out << static_cast<int>(v); }
31
32 // Structure to keep a reference to value, that will be ostreamed lower
33 template <class T>
34 struct io_reference {
35 const T& value;
36 };
37
38 // Output each field of io_reference::value
39 template <class T>
40 std::ostream& operator<<(std::ostream& out, io_reference<T>&& x) {
41 const char* sep = "";
42
43 boost::pfr::for_each_field(x.value, [&](const auto& v) {
44 out << std::exchange(obj&: sep, new_val: ", ");
45 detail::print_each(out, v);
46 });
47 return out;
48 }
49}
50
51// Definition:
52template <class T>
53auto my_io(const T& value) {
54 return detail::io_reference<T>{value};
55}
56
57} // namespace my_ns
58//] [/pfr_sample_printing]
59
60
61#include <iostream>
62#include <sstream>
63
64int main() {
65 struct foo {std::uint8_t a, b;};
66
67 std::ostringstream oss;
68 oss << my_ns::my_io(value: foo{.a: 42, .b: 22});
69
70 if (oss.str() != "42, 22") {
71 return 1;
72 }
73
74 struct two_big_strings {
75 std::string first;
76 std::string second;
77 };
78
79#if BOOST_PFR_USE_CPP17 || BOOST_PFR_USE_LOOPHOLE
80 const char* huge_string = "Some huge string that should not fit into std::string SSO."
81 "And by 'huge' I mean really HUGE string with multiple statements and a lot of periods........."
82 ;
83
84 oss.str(s: {});
85 oss << my_ns::my_io(value: two_big_strings{
86 .first: huge_string, .second: huge_string
87 });
88
89 if (oss.str() != huge_string + std::string(", ") + huge_string) {
90 return 2;
91 }
92#endif
93
94 return 0;
95}
96

source code of boost/libs/pfr/example/sample_printing.cpp