From b67893d92e22f486b106128f0e2682d058ed36d7 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Sat, 16 Sep 2017 21:19:41 +0300 Subject: [PATCH] Updated docs and enabled Loophole by default --- README.md | 13 ++++------- doc/pfr.qbk | 35 +++++++++++++++++++---------- include/boost/pfr/detail/config.hpp | 2 +- include/boost/pfr/precise/core.hpp | 10 ++++----- 4 files changed, 33 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index fe1dbcb..27812a5 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ Develop: | [![Build Status](https://travis-ci.org/apolukhin/magic_get.svg Master: | [![Build Status](https://travis-ci.org/apolukhin/magic_get.svg?branch=master)](https://travis-ci.org/apolukhin/magic_get) | [![Coverage Status](https://coveralls.io/repos/github/apolukhin/magic_get/badge.png?branch=master)](https://coveralls.io/github/apolukhin/magic_get?branch=master) | -### C++14 Motivating Example +### Motivating Example #1 ```c++ // requires: C++14 #include @@ -42,9 +42,10 @@ Outputs: my_struct has 3 fields: {100, H, 3.14159} ``` -### C++17 Motivating Example +### Motivating Example #2 ```c++ +// requires: C++14 #include #include "boost/pfr.hpp" @@ -54,7 +55,7 @@ struct my_struct { // no ostream operator defined! }; int main() { - using namespace boost::pfr::ops; // C++17 out-of-the-box ostream operators for aggregate initializables! + using namespace boost::pfr::ops; // out-of-the-box ostream operators for aggregate initializables! my_struct s{{"Das ist fantastisch!"}, 100}; std::cout << "my_struct has " << boost::pfr::tuple_size::value @@ -74,14 +75,8 @@ my_struct has 2 fields: {"Das ist fantastisch!", 100} General: * C++14 compatible compiler (GCC-5.0+, Clang, ...) * Static variables are ignored - -C++14 limitations: * T must be constexpr aggregate initializable and must not contain references nor bitfields -C++17 limitations: -* T must be aggregate initializable and must not contain arrays (but may contain `std::array` like classes) - - ### License Distributed under the [Boost Software License, Version 1.0](http://boost.org/LICENSE_1_0.txt). diff --git a/doc/pfr.qbk b/doc/pfr.qbk index c0d4363..727fc07 100644 --- a/doc/pfr.qbk +++ b/doc/pfr.qbk @@ -63,16 +63,9 @@ Boost.Precise and Flat Reflection (Boost.PFR) adds following out-of-the-box func [section Flat or Precise functions to chose] All the functions that have `flat_` prefix and are declared in `boost/pfr/flat/*` headers the [*flat] functions, other function are [*precise] and are declared in `boost/pfr/precise/*`. In previous example you've seen how the the flattening works. -Flat functions are more limited in their reflection capabilities, but guarantee to not affect debug and release builds in C++14 mode (no additional code would be produced). - -Precise functions have almost unlimited reflection capabilities, but may produce additional code in C++14 mode in debug builds and even in release builds (on old compilers or compilers with bad optimizers). - -Here's how to chose your functions: - -* If you work only with POD types and wish them flattened - use [*flat] functions -* If you use C++17 - use [*precise] functions -* If you work only with flat POD types in C++14 - use [*flat] functions -* If you have modern compiler in C++14 mode and work with non-POD literal types with some hierarchy - you are forced to use [*precise] functions +* If you wish types flattened - use [*flat] functions +* If you use types with C arrays - use [*flat] functions +* Otherwise use [*precise] functions [endsect] @@ -289,6 +282,21 @@ Following examples use definition from above: [endsect] +[section Configuration Macro] + +By default Boost.PFR [*auto-detects your compiler abilities] and automatically defines the configuration macro into appropriate values. If you wish to override that behavior, just define: +[table:linkmacro Macros + [[Macro name] [Effect]] + [[*BOOST_PFR_USE_CPP17*] [Define to `1` if you wish to use structured bindings and other C++17 features for reflection. Define to `0` otherwize.]] + [[*BOOST_PFR_USE_LOOPHOLE*] [Define to `1` if you wish to exploit [@http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2118 CWG 2118] for reflection. Define to `0` otherwize.]] +] + +Note that disabling [*Loophole] in C++14 significantly limitates the reflection abilities of the library. See next section for more info. + + +[endsect] + + [section Requirements and Limitations] [note Boost.PFR does not depend on any Boost library. You may use it's headers even without Boost. ] @@ -300,11 +308,10 @@ Following examples use definition from above: [*Flat] functions limitations: * T must be POD and must not contain references nor bitfields -* T must not contain pointers to user defined types * Enums will be returned as their underlying type * All the methods that provide access to fields have a `reinterpret_cast` to an unrelated type. All the possible efforts and compiler specific tricks were used to avoid issues. But strictly speaking *this is an Undefined Behavior. -C++14 [*precise] functions limitations (C++17 fixes those): +C++14 [*precise] functions limitations with manually disabled [*Loophole](C++17 or not disabling Loophole fixes those): * T must be constexpr aggregate initializable and all it's fields must be constexpr default constructible * [funcref boost::pfr::get], [funcref boost::pfr::structure_to_tuple], [funcref boost::pfr::structure_tie], [headerref boost/pfr/precise/core.hpp boost::pfr::tuple_element] require T to be a flat POD type @@ -327,6 +334,8 @@ Short description: * C++17: # at compile-time: structured bindings are used to decompose a type `T` to known amount of fields fields * C++14: + # Same approach as with [*flat] functions + * C++14 with disabled [*Loophole]: # at compile-time: use flat reflection if it could precisely reflect the type. Otherwise: # at compile-time: let `I` be is an index of current field, it equals 0 # at run-time: `T` is constructed and field `I` is aggregate initialized using a separate instance of structure that is convertible to anything [note Additional care is taken to make sure that all the information about `T` is available to the compiler and that operations on `T` have no side effects, so the compiler can optimize away the unnecessary temporary objects.] @@ -343,6 +352,8 @@ Long description: [@https://www.youtube.com/watch?v=abdeAew3gmQ Antony Polukhin: Great thanks to Bruno Dutra for showing the technique to precisely reflect aggregate initializable type in C++14 [@https://github.com/apolukhin/magic_get/issues/5 Manual type registering/structured bindings might be unnecessary]. +Great thanks to Alexandr Poltavsky for initial implementation the [*Loophole] technique and for describing it [@http://alexpolt.github.io/type-loophole.html in his blog]. + [endsect] [section Reference] diff --git a/include/boost/pfr/detail/config.hpp b/include/boost/pfr/detail/config.hpp index b5ab203..908531f 100644 --- a/include/boost/pfr/detail/config.hpp +++ b/include/boost/pfr/detail/config.hpp @@ -16,7 +16,7 @@ #endif #ifndef BOOST_PFR_USE_LOOPHOLE -# define BOOST_PFR_USE_LOOPHOLE 0 +# define BOOST_PFR_USE_LOOPHOLE 1 #endif #ifndef BOOST_PFR_USE_CPP17 diff --git a/include/boost/pfr/precise/core.hpp b/include/boost/pfr/precise/core.hpp index 116453f..66f6da4 100644 --- a/include/boost/pfr/precise/core.hpp +++ b/include/boost/pfr/precise/core.hpp @@ -27,7 +27,7 @@ namespace boost { namespace pfr { /// \brief Returns reference or const reference to a field with index `I` in aggregate T. /// -/// \b Requires: C++17 or \flatpod{C++14 flat POD}. +/// \b Requires: C++17 or \flatpod{C++14 flat POD or C++14 with not disabled Loophole}. /// /// \rcast14 /// @@ -53,7 +53,7 @@ constexpr decltype(auto) get(T& val) noexcept { /// \brief `tuple_element` has a `typedef type-of-a-field-with-index-I-in-aggregate-T type;` /// -/// \b Requires: C++17 or \flatpod{C++14 flat POD}. +/// \b Requires: C++17 or \flatpod{C++14 flat POD or C++14 with not disabled Loophole}. /// /// \b Example: /// \code @@ -65,7 +65,7 @@ using tuple_element = detail::sequence_tuple::tuple_element::type; /// \brief Creates an `std::tuple` from an aggregate T. /// -/// \b Requires: C++17 or \flatpod{C++14 flat POD}. +/// \b Requires: C++17 or \flatpod{C++14 flat POD or C++14 with not disabled Loophole}. /// /// \rcast14 /// @@ -99,7 +99,7 @@ constexpr auto structure_to_tuple(const T& val) noexcept { /// \brief Creates an `std::tuple` with lvalue references to fields of an aggregate T. /// -/// \b Requires: C++17 or \flatpod{C++14 flat POD}. +/// \b Requires: C++17 or \flatpod{C++14 flat POD or C++14 with not disabled Loophole}. /// /// \rcast14 ///