From f40d2f773ab828b11db54815726142fe08b53144 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Sun, 11 Oct 2020 21:09:14 +0300 Subject: [PATCH] cleanup quck examples --- doc/pfr.qbk | 48 +++--- example/quick_examples.cpp | 195 ++++++++++++++++--------- include/boost/pfr/detail/detectors.hpp | 36 +++-- include/boost/pfr/functors.hpp | 25 ++-- include/boost/pfr/ops.hpp | 105 +++++++------ 5 files changed, 238 insertions(+), 171 deletions(-) diff --git a/doc/pfr.qbk b/doc/pfr.qbk index 27eef30..2bf0b0d 100644 --- a/doc/pfr.qbk +++ b/doc/pfr.qbk @@ -136,50 +136,46 @@ PFR is a header only library that does not depend on Boost. You can just copy th [section Short Examples for the Impatient] -Examples in the table use the following definition: - [import ../example/quick_examples.cpp] -[pfr_quick_examples_structures] - [table:quick_examples -[[ Code snippet ] [ `var` content or output ] [ Function description: ]] +[[ Code snippet ] [ Functions reference: ]] [ - [ [pfr_quick_examples_get_1] ] - [ `var == {A {1, 2.0}}` ] - [ [funcref boost::pfr::get get] ] -][ - [ [pfr_quick_examples_get_2] ] - [ `var == {A, {777, 42.01}}` ] - [ [funcref boost::pfr::get get] ] + [ [pfr_quick_examples_get] ] + [ [funcref boost::pfr::get] ] ][ [ [pfr_quick_examples_ops] ] - [ assert succeeds ] - [ [headerref boost/pfr/ops.hpp using\u00A0namespace\u00A0ops;] ] + [ + [headerref boost/pfr/ops.hpp Header boost/pfr/ops.hpp] + ] ][ [ [pfr_quick_examples_for_each] ] - [ `var == {B, {787, 103.142}}` ] - [ [funcref boost::pfr::for_each_field for_each_field] ] + [ + [funcref boost::pfr::for_each_field] + + [funcref boost::pfr::io] + ] +][ + [ [pfr_quick_examples_functions_for] ] + [ [macroref BOOST_PFR_FUNCTIONS_FOR] ] +][ + [ [pfr_quick_examples_eq_fields] ] + [ [headerref boost/pfr/ops.hpp Header boost/pfr/ops_fields.hpp ] ][ [ [pfr_quick_examples_for_each_idx] ] - [ ```0: char -1: quick_examples_ns::foo -``` ] - [ [funcref boost::pfr::for_each_field for_each_field] ] + [ [funcref boost::pfr::for_each_field] ] ][ [ [pfr_quick_examples_tuple_size] ] - [ `tuple_size: 2` ] - [ [classref boost::pfr::tuple_size tuple_size] ] + [ [classref boost::pfr::tuple_size] ] ][ [ [pfr_quick_examples_structure_to_tuple] ] - [ `var == {A, {777, 3.14159}}` ] - [ [funcref boost::pfr::structure_to_tuple structure_to_tuple] ] + [ [funcref boost::pfr::structure_to_tuple] ] ][ [ [pfr_quick_examples_structure_tie] ] - [ `var == {A, {1, 2.0}}` ] - [ [funcref boost::pfr::structure_tie structure_tie] ] + [ [funcref boost::pfr::structure_tie] ] ]] +] [endsect] diff --git a/example/quick_examples.cpp b/example/quick_examples.cpp index fa945b0..8c3fc71 100644 --- a/example/quick_examples.cpp +++ b/example/quick_examples.cpp @@ -12,61 +12,65 @@ #include #include - -//[pfr_quick_examples_structures -struct foo { - int integer; - double real; - - void operator +=(int v) { - integer += v * 10; - real += v * 100; - } -}; - -struct bar { - char character; - foo f; -}; - -bar var{'A', {777, 3.141593}}; -//] - -inline std::ostream& operator<<(std::ostream& os, const bar& b) { - return os << '{' << b.character << ", {" << b.f.integer << ", " << b.f.real << "}}"; -} - void test_examples() { #if BOOST_PFR_USE_CPP17 { //[pfr_quick_examples_ops - struct test { std::string f1; std::string_view f2; }; - assert(boost::pfr::gt(test{"abc", ""}, test{"aaa", "zomg"})); + // Assert equality. + // Note that the equality operator for structure is not defined. + + struct test { + std::string f1; + std::string_view f2; + }; + + assert( + boost::pfr::eq(test{"aaa", "zomg"}, test{"aaa", "zomg"}) + ); //] } #endif - - { - bar var{'A', {777, 3.141593}}; - -//[pfr_quick_examples_for_each - // increments first field on 1, calls foo::operator+= for second field + + { +//[pfr_quick_examples_for_each + // Increment each field of the variable on 1 and + // output the content of the variable. + + struct test { + int f1; + long f2; + }; + + test var{42, 43}; + boost::pfr::for_each_field(var, [](auto& field) { field += 1; }); -//] - - std::cout << "flat_for_each_field outputs:\n" << var << '\n'; - } - - { - bar var{'A', {777, 3.141593}}; -//[pfr_quick_examples_for_each_idx - boost::pfr::for_each_field(var, [](auto& field, std::size_t idx) { - std::cout << idx << ": " - << boost::typeindex::type_id_runtime(field) << '\n'; + // Outputs: {43, 44} + std::cout << boost::pfr::io(var); +//] + } + + { +//[pfr_quick_examples_for_each_idx + // Iterate over fields of a varible and output index and + // type of a variable. + + struct tag0{}; + struct tag1{}; + struct sample { + tag0 a; + tag1 b; + }; + + // Outputs: + // 0: tag0 + // 1: tag1 + boost::pfr::for_each_field(sample{}, [](const auto& field, std::size_t idx) { + std::cout << '\n' << idx << ": " + << boost::typeindex::type_id_runtime(field); }); //] } @@ -74,55 +78,104 @@ void test_examples() { { //[pfr_quick_examples_tuple_size - std::cout << "tuple_size: " - << boost::pfr::tuple_size::value << '\n'; + struct some { int a,b,c,d,e; }; + + std::cout << "Fields count in structure: " + << boost::pfr::tuple_size::value // Outputs: 5 + << '\n'; +//] + } + + { +//[pfr_quick_examples_get + // Get field by index and assign new value to that field + + struct sample { + char c; + float f; + }; + + sample var{}; + boost::pfr::get<1>(var) = 42.01; + + std::cout << var.f; // Outputs: 42.01 //] } #if BOOST_PFR_USE_CPP17 || BOOST_PFR_USE_LOOPHOLE { - bar var{'A', {777, 3.141593}}; -//[pfr_quick_examples_get_1 - boost::pfr::get<1>(var) = foo{1, 2}; // C++17 or Loophole is required -//] - std::cout << "boost::pfr::get<1>(var) outputs:\n" << var << '\n'; - } -#endif - - { - bar var{'A', {777, 3.141593}}; -//[pfr_quick_examples_get_2 - boost::pfr::get<1>(var.f) = 42.01; -//] - std::cout << "boost::pfr::get<1>(var.f) outputs:\n" << var << '\n'; - } - -#if BOOST_PFR_USE_CPP17 || BOOST_PFR_USE_LOOPHOLE - { - bar var{'A', {777, 3.141593}}; //[pfr_quick_examples_structure_to_tuple - // C++17 or Loophole is required + struct foo { int a, b; }; + struct other { + char c; + foo nested; + }; + + other var{'A', {3, 4}}; std::tuple t = boost::pfr::structure_to_tuple(var); - std::get<1>(t) = foo{1, 2}; + assert(std::get<0>(t) == 'A'); + assert( + boost::pfr::eq(std::get<1>(t), foo{3, 4}) + ); //] - std::cout << "boost::pfr::structure_to_tuple(var) :\n" << var << '\n'; } #endif #if BOOST_PFR_USE_CPP17 || BOOST_PFR_USE_LOOPHOLE { - bar var{'A', {777, 3.141593}}; //[pfr_quick_examples_structure_tie - // C++17 or Loophole is required + struct foo { int a, b; }; + struct other { + char c; + foo f; + }; + + other var{'A', {14, 15}}; std::tuple t = boost::pfr::structure_tie(var); std::get<1>(t) = foo{1, 2}; + + std::cout << boost::pfr::io(var.f); // Outputs: {1, 2} //] - std::cout << "boost::pfr::structure_tie(var) :\n" << var << '\n'; } #endif -} // void test_examples() { +} // void test_examples() +//[pfr_quick_examples_functions_for +// Define all the comparison and IO operators for my_structure type along +// with hash_value function. + +#include + +namespace my_namespace { + struct my_structure { + int a,b,c,d,e,f,g; + // ... + }; + BOOST_PFR_FUNCTIONS_FOR(my_structure) +} +//] + +//[pfr_quick_examples_eq_fields +// Define only the equality and inequality operators for my_eq_ne_structure. + +#include + +namespace my_namespace { + struct my_eq_ne_structure { + float a,b,c,d,e,f,g; + // ... + }; + + inline bool operator==(const my_eq_ne_structure& x, const my_eq_ne_structure& y) { + return boost::pfr::eq_fields(x, y); + } + + inline bool operator!=(const my_eq_ne_structure& x, const my_eq_ne_structure& y) { + return boost::pfr::ne_fields(x, y); + } +} +//] int main() { test_examples(); diff --git a/include/boost/pfr/detail/detectors.hpp b/include/boost/pfr/detail/detectors.hpp index 061b4b7..2ee04e3 100644 --- a/include/boost/pfr/detail/detectors.hpp +++ b/include/boost/pfr/detail/detectors.hpp @@ -9,52 +9,58 @@ #include +#include #include namespace boost { namespace pfr { namespace detail { ///////////////////// `value` is true if Detector does not compile (SFINAE) - struct success{}; + struct can_not_apply{}; template