| 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 | #include <cassert> |
| 8 | #include <iostream> |
| 9 | #include <unordered_set> |
| 10 | #include <set> |
| 11 | |
| 12 | #include <boost/pfr.hpp> |
| 13 | #include <boost/type_index.hpp> |
| 14 | |
| 15 | // boost-no-inspect |
| 16 | void test_examples() { |
| 17 | |
| 18 | #if BOOST_PFR_USE_CPP17 |
| 19 | { |
| 20 | //[pfr_quick_examples_ops |
| 21 | // Assert equality. |
| 22 | // Note that the equality operator for structure is not defined. |
| 23 | |
| 24 | struct test { |
| 25 | std::string f1; |
| 26 | std::string_view f2; |
| 27 | }; |
| 28 | |
| 29 | assert( |
| 30 | boost::pfr::eq(test{"aaa" , "zomg" }, test{"aaa" , "zomg" }) |
| 31 | ); |
| 32 | //] |
| 33 | } |
| 34 | #endif |
| 35 | |
| 36 | { |
| 37 | //[pfr_quick_examples_for_each |
| 38 | // Increment each field of the variable on 1 and |
| 39 | // output the content of the variable. |
| 40 | |
| 41 | struct test { |
| 42 | int f1; |
| 43 | long f2; |
| 44 | }; |
| 45 | |
| 46 | test var{.f1: 42, .f2: 43}; |
| 47 | |
| 48 | boost::pfr::for_each_field(value&: var, func: [](auto& field) { |
| 49 | field += 1; |
| 50 | }); |
| 51 | |
| 52 | // Outputs: {43, 44} |
| 53 | std::cout << boost::pfr::io(value&: var); |
| 54 | //] |
| 55 | } |
| 56 | |
| 57 | { |
| 58 | //[pfr_quick_examples_for_each_idx |
| 59 | // Iterate over fields of a variable and output index and |
| 60 | // type of a variable. |
| 61 | |
| 62 | struct tag0{}; |
| 63 | struct tag1{}; |
| 64 | struct sample { |
| 65 | tag0 a; |
| 66 | tag1 b; |
| 67 | }; |
| 68 | |
| 69 | // Outputs: |
| 70 | // 0: tag0 |
| 71 | // 1: tag1 |
| 72 | boost::pfr::for_each_field(value: sample{}, func: [](const auto& field, std::size_t idx) { |
| 73 | std::cout << '\n' << idx << ": " |
| 74 | << boost::typeindex::type_id_runtime(field); |
| 75 | }); |
| 76 | //] |
| 77 | } |
| 78 | |
| 79 | |
| 80 | { |
| 81 | //[pfr_quick_examples_tuple_size |
| 82 | // Getting fields count of some structure |
| 83 | |
| 84 | struct some { int a,b,c,d,e; }; |
| 85 | |
| 86 | std::cout << "Fields count in structure: " |
| 87 | << boost::pfr::tuple_size<some>::value // Outputs: 5 |
| 88 | << '\n'; |
| 89 | //] |
| 90 | } |
| 91 | |
| 92 | { |
| 93 | //[pfr_quick_examples_get |
| 94 | // Get field by index/type and assign new value to that field |
| 95 | |
| 96 | struct sample { |
| 97 | char c; |
| 98 | float f; |
| 99 | }; |
| 100 | |
| 101 | sample var{}; |
| 102 | boost::pfr::get<1>(val&: var) = 42.01f; |
| 103 | boost::pfr::get<char>(val&: var) = 'A'; |
| 104 | |
| 105 | std::cout << var.c << var.f; // Outputs: A 42.01 |
| 106 | //] |
| 107 | } |
| 108 | |
| 109 | // Disabling for MSVC as it gives a hard error on using local types: |
| 110 | // |
| 111 | // error C7631: |
| 112 | // 'boost::pfr::detail::do_not_use_PFR_with_local_types<test_examples::sample>': |
| 113 | // variable with internal linkage declared but not defined |
| 114 | #if BOOST_PFR_CORE_NAME_ENABLED && BOOST_PFR_USE_CPP17 && !defined(_MSC_VER) |
| 115 | { |
| 116 | //[pfr_quick_examples_get_name |
| 117 | // Get name of field by index |
| 118 | |
| 119 | struct sample { |
| 120 | int f_int; |
| 121 | long f_long; |
| 122 | }; |
| 123 | |
| 124 | std::cout << boost::pfr::get_name<0, sample>() |
| 125 | << boost::pfr::get_name<1, sample>(); // Outputs: f_int f_long |
| 126 | //] |
| 127 | } |
| 128 | #endif |
| 129 | |
| 130 | #if BOOST_PFR_USE_CPP17 || BOOST_PFR_USE_LOOPHOLE |
| 131 | { |
| 132 | //[pfr_quick_examples_structure_to_tuple |
| 133 | // Getting a std::tuple of values from structures fields |
| 134 | |
| 135 | struct foo { int a, b; }; |
| 136 | struct other { |
| 137 | char c; |
| 138 | foo nested; |
| 139 | }; |
| 140 | |
| 141 | other var{.c: 'A', .nested: {.a: 3, .b: 4}}; |
| 142 | std::tuple<char, foo> t = boost::pfr::structure_to_tuple(val: var); |
| 143 | assert(std::get<0>(t) == 'A'); |
| 144 | assert( |
| 145 | boost::pfr::eq(std::get<1>(t), foo{3, 4}) |
| 146 | ); |
| 147 | //] |
| 148 | } |
| 149 | #endif |
| 150 | |
| 151 | #if BOOST_PFR_USE_CPP17 || BOOST_PFR_USE_LOOPHOLE |
| 152 | { |
| 153 | //[pfr_quick_examples_structure_tie |
| 154 | // Getting a std::tuple of references to structure fields |
| 155 | |
| 156 | struct foo { int a, b; }; |
| 157 | struct other { |
| 158 | char c; |
| 159 | foo f; |
| 160 | }; |
| 161 | |
| 162 | other var{.c: 'A', .f: {.a: 14, .b: 15}}; |
| 163 | std::tuple<char&, foo&> t = boost::pfr::structure_tie(val&: var); |
| 164 | std::get<1>(t&: t) = foo{.a: 1, .b: 2}; |
| 165 | |
| 166 | std::cout << boost::pfr::io(value&: var.f); // Outputs: {1, 2} |
| 167 | //] |
| 168 | } |
| 169 | #endif |
| 170 | |
| 171 | } // void test_examples() |
| 172 | |
| 173 | //[pfr_quick_examples_functions_for |
| 174 | // Define all the comparison and IO operators for my_structure type along |
| 175 | // with hash_value function. |
| 176 | |
| 177 | #include <boost/pfr/functions_for.hpp> |
| 178 | |
| 179 | namespace my_namespace { |
| 180 | struct my_structure { |
| 181 | int a,b,c,d,e,f,g; |
| 182 | // ... |
| 183 | }; |
| 184 | BOOST_PFR_FUNCTIONS_FOR(my_structure) |
| 185 | } |
| 186 | //] |
| 187 | |
| 188 | //[pfr_quick_examples_eq_fields |
| 189 | // Define only the equality and inequality operators for my_eq_ne_structure. |
| 190 | |
| 191 | #include <boost/pfr/functions_for.hpp> |
| 192 | |
| 193 | namespace my_namespace { |
| 194 | struct my_eq_ne_structure { |
| 195 | float a,b,c,d,e,f,g; |
| 196 | // ... |
| 197 | }; |
| 198 | |
| 199 | inline bool operator==(const my_eq_ne_structure& x, const my_eq_ne_structure& y) { |
| 200 | return boost::pfr::eq_fields(lhs: x, rhs: y); |
| 201 | } |
| 202 | |
| 203 | inline bool operator!=(const my_eq_ne_structure& x, const my_eq_ne_structure& y) { |
| 204 | return boost::pfr::ne_fields(lhs: x, rhs: y); |
| 205 | } |
| 206 | } |
| 207 | //] |
| 208 | |
| 209 | int main() { |
| 210 | test_examples(); |
| 211 | } |
| 212 | |