• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016-2021 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 
14 namespace 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
22 template <class T>
23 auto my_io(const T& value);
24 
25 namespace detail {
26     // Helpers to print individual values
27     template <class T>
print_each(std::ostream & out,const T & v)28     void print_each(std::ostream& out, const T& v) { out << v; }
print_each(std::ostream & out,std::uint8_t v)29     void print_each(std::ostream& out, std::uint8_t v) { out << static_cast<unsigned>(v); }
print_each(std::ostream & out,std::int8_t 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>
operator <<(std::ostream & out,io_reference<T> && x)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(sep, ", ");
45             detail::print_each(out, v);
46         });
47         return out;
48     }
49 }
50 
51 // Definition:
52 template <class T>
my_io(const T & value)53 auto 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 
main()64 int main() {
65     struct foo {std::uint8_t a, b;};
66 
67     std::ostringstream oss;
68     oss << my_ns::my_io(foo{42, 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({});
85     oss << my_ns::my_io(two_big_strings{
86         huge_string, 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