diff --git a/doc/pfr.qbk b/doc/pfr.qbk index e260968..4808f7e 100644 --- a/doc/pfr.qbk +++ b/doc/pfr.qbk @@ -18,6 +18,9 @@ Boost.PFR is a library for very basic reflection that gives you access to struct `std::tuple` and `std::pair` are great for generic programming, however they have disadvantages. First of all, code that uses them becomes barely readable. Consider two definitions: +[table:tuples_vs_aggregates +[[ Tuple ] [ Aggregate ]] +[[ ``` using auth_info_tuple = std::tuple< std::int64_t, @@ -25,14 +28,17 @@ using auth_info_tuple = std::tuple< std::int64_t, std::time_t >; - +``` +][ +``` struct auth_info_aggregate { std::int64_t id; std::int64_t session_id; std::int64_t source_id; - std::time_t valid_till; + std::time_t valid_till; }; ``` +]] Definition via [@https://en.cppreference.com/w/cpp/language/aggregate_initialization aggregate initializable] structure is much more clear. Same story with usages: `return std::get<1>(value);` vs. `return value.session_id;`. @@ -211,6 +217,8 @@ Examples in the table use the following definition: [section Tutorial] +[import ../example/examples.cpp] + [section Accessing structure member by index] [pfr_example_get] [endsect] [section Custom printing of aggregates] [pfr_sample_printing] [endsect] [/ [section Counting fields] [pfr_example_tuple_size] [endsect] ] diff --git a/example/examples.cpp b/example/examples.cpp new file mode 100644 index 0000000..08ba490 --- /dev/null +++ b/example/examples.cpp @@ -0,0 +1,110 @@ +// Copyright 2016-2020 Antony Polukhin + +// Distributed under the Boost Software License, Version 1.0. +// (See the accompanying file LICENSE_1_0.txt +// or a copy at .) + +#include + + +//[pfr_sample_printing +/*` + The following example shows how to customize printing and write your own testing helper for structures: +*/ +#include +#include + +namespace my_testing { + +template +void print_each(std::ostream& out, const T& v) { out << v; } +void print_each(std::ostream& out, std::uint8_t v) { out << static_cast(v); } +void print_each(std::ostream& out, std::int8_t v) { out << static_cast(v); } + +template +void print(const T& value) { + const char* sep = ""; + + boost::pfr::for_each_field(value, [&](const auto& v) { + std::cerr << std::exchange(sep, ", "); + print_each(std::cerr, v); + }); +} + +/// Usage: +/// struct foo {std::uint8_t a, b;}; +/// foo get_foo(); +/// ... +/// test_eq(foo{42, 22}, get_foo()); +/// +/// Output: +/// 42, 22 != 42, 24 +template +void test_eq(const T& x, const T& y) { + using namespace boost::pfr::ops; + if (x == y) return; + + print(x); + std::cerr << " != "; + print(y); +} + +} // namespace my_testing +//] [/pfr_sample_printing] + + +//[pfr_example_get +/*` + The following example shows how to access structure fields by index using [funcref boost::pfr::get]. + + Let's define some structure: +*/ +#include + +struct foo { // defining structure + int some_integer; + char c; +}; + +/*` + We can access fields of that structure by index: +*/ +foo f {777, '!'}; +auto& r1 = boost::pfr::get<0>(f); // accessing field with index 0, returns reference to `foo::some_integer` +auto& r2 = boost::pfr::get<1>(f); // accessing field with index 1, returns reference to `foo::c` +//] [/pfr_example_get] + +//[pfr_example_tuple_size +/*` + The following example shows how to count fields using [classref boost::pfr::tuple_size]. +*/ +#include + +struct foo2 { // defining structure + int some_integer; + char c; + short some_other_field; +}; + + +static_assert( + boost::pfr::tuple_size::value // returns total count of fields in `foo2` + == 3, "" +); + +static_assert( + boost::pfr::tuple_size::value // works with arrays too! + == 100, "" +); +//] [/pfr_example_tuple_size] + + +struct foo_printing_test {std::uint8_t a, b;}; +foo_printing_test get_foo_printing_test() { return foo_printing_test{42, 24}; } + +int main() { + my_testing::test_eq( + foo_printing_test{42, 22}, + get_foo_printing_test() + ); +} diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index bb6870c..8642e3f 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -62,7 +62,7 @@ local BLACKLIST_TESTS_FOR_CLASSIC = tie_anonymous ; -for local source_file in [ glob ./run/*.cpp ] ../example/quick_examples.cpp +for local source_file in [ glob ./run/*.cpp ] [ glob ../example/*.cpp ] { local target_name = $(source_file[1]:B) ; pfr_tests += [ run $(source_file) : : : $(STRUCTURED_BINDING_ENGINE) : $(target_name)_sb ] ;