mirror of
https://github.com/boostorg/pfr.git
synced 2026-01-22 05:22:32 +00:00
Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
50d58a2e84 | ||
|
|
76ac44a9ca | ||
|
|
4205a2e553 | ||
|
|
89b1d45ff7 | ||
|
|
26867f47b7 | ||
|
|
b9166fd38e | ||
|
|
915bd9217c | ||
|
|
0885412a7d | ||
|
|
86ebac6e0c | ||
|
|
39e9b4c5fe | ||
|
|
01fd8db5b4 |
259
doc/pfr.qbk
259
doc/pfr.qbk
@@ -1,4 +1,4 @@
|
||||
[library Boost.Precise and Flat Reflection
|
||||
[library Boost.PFR
|
||||
[quickbook 1.6]
|
||||
[version 1.0]
|
||||
[copyright 2016-2020 Antony Polukhin]
|
||||
@@ -17,7 +17,7 @@ In C++ we have:
|
||||
* tuples - types that provide access to members by index. Those are useful for generic programming.
|
||||
* structures - types with named fields that do not provide access to members by index. Those are just easy to use.
|
||||
|
||||
This library provides tuple like methods for aggregate initializable structures, making them usable in contexts were only tuples were useful.
|
||||
This library provides tuple like methods for aggregate initializable structures, making them usable in contexts where only tuples were useful.
|
||||
|
||||
[note All you have to do is to add `#include <boost/pfr.hpp>`.
|
||||
|
||||
@@ -47,25 +47,130 @@ Boost.Precise and Flat Reflection (Boost.PFR) adds following out-of-the-box func
|
||||
* methods for cooperation with `std::tuple`
|
||||
* methods to visit each field of the structure
|
||||
|
||||
PFR is a header only library that does not depend on Boost. You can just copy the content of the "include" folder [@https://github.com/apolukhin/magic_get from the github] into your project, and the library would work fine.
|
||||
|
||||
[warning This is not an official Boost library! It wasn't reviewed and can't be downloaded from www.boost.org. This library is available to the community to know real interest and get comments for refinement. The intention is to submit library to formal review, if community think that it is interesting!]
|
||||
|
||||
[caution This is a C++14 library! Pre C++14 compilers (C++11, C++03...) are not supported]
|
||||
[caution Recommended C++ Standards are C++17 and above]
|
||||
|
||||
[caution Library requires at least C++14! Pre C++14 compilers (C++11, C++03...) are not supported]
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
[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: ]]
|
||||
[
|
||||
[ [pfr_quick_examples_get_1] ]
|
||||
[ `var == {A {1, 2.0}}` ]
|
||||
[ [funcref boost::pfr::get get] ]
|
||||
][
|
||||
[ [pfr_quick_examples_flat_get_1] ]
|
||||
[ `var == {A, {1, 3.14159}}` ]
|
||||
[ [funcref boost::pfr::flat_get flat_get] ]
|
||||
][
|
||||
[ [pfr_quick_examples_get_2] ]
|
||||
[ `var == {A, {777, 42.01}}` ]
|
||||
[ [funcref boost::pfr::get get] ]
|
||||
][
|
||||
[ [pfr_quick_examples_flat_get_2] ]
|
||||
[ `var == {A, {777, 42.01}}` ]
|
||||
[ [funcref boost::pfr::flat_get flat_get] ]
|
||||
][
|
||||
[ [pfr_quick_examples_flat_functors_uset] ]
|
||||
[ `my_uset` constains `var` ]
|
||||
[
|
||||
[classref boost::pfr::flat_hash flat_hash]
|
||||
|
||||
[classref boost::pfr::flat_equal_to flat_equal_to]
|
||||
]
|
||||
][
|
||||
[ [pfr_quick_examples_flat_functors_set] ]
|
||||
[ `my_set` constains `var` ]
|
||||
[ [classref boost::pfr::flat_less flat_less] ]
|
||||
][
|
||||
[ [pfr_quick_examples_flat_ops] ]
|
||||
[ assert succeeds ]
|
||||
[ [headerref boost/pfr/flat/ops.hpp using\u00A0namespace\u00A0flat_ops;] ]
|
||||
][
|
||||
[ [pfr_quick_examples_ops] ]
|
||||
[ assert succeeds ]
|
||||
[ [headerref boost/pfr/precise/ops.hpp using\u00A0namespace\u00A0ops;] ]
|
||||
][
|
||||
[ [pfr_quick_examples_flat_for_each] ]
|
||||
[ `var == {B, {778, 4.14159}}` ]
|
||||
[ [funcref boost::pfr::flat_for_each_field flat_for_each_field] ]
|
||||
][
|
||||
[ [pfr_quick_examples_for_each] ]
|
||||
[ `var == {B, {787, 103.142}}` ]
|
||||
[ [funcref boost::pfr::for_each_field for_each_field] ]
|
||||
][
|
||||
[ [pfr_quick_examples_flat_for_each_idx] ]
|
||||
[ ```0: char
|
||||
1: int
|
||||
2: double
|
||||
``` ]
|
||||
[ [funcref boost::pfr::flat_for_each_field flat_for_each_field] ]
|
||||
][
|
||||
[ [pfr_quick_examples_for_each_idx] ]
|
||||
[ ```0: char
|
||||
1: quick_examples_ns::foo
|
||||
``` ]
|
||||
[ [funcref boost::pfr::for_each_field for_each_field] ]
|
||||
][
|
||||
[ [pfr_quick_examples_tuple_size] ]
|
||||
[ `tuple_size: 2` ]
|
||||
[ [classref boost::pfr::tuple_size tuple_size] ]
|
||||
][
|
||||
[ [pfr_quick_examples_flat_tuple_size] ]
|
||||
[ `flat_tuple_size: 3` ]
|
||||
[ [classref boost::pfr::flat_tuple_size flat_tuple_size] ]
|
||||
][
|
||||
[ [pfr_quick_examples_structure_to_tuple] ]
|
||||
[ `var == {A, {777, 3.14159}}` ]
|
||||
[ [funcref boost::pfr::structure_to_tuple structure_to_tuple] ]
|
||||
][
|
||||
[ [pfr_quick_examples_flat_structure_to_tuple] ]
|
||||
[ `var == {A, {777, 3.14159}}` ]
|
||||
[ [funcref boost::pfr::flat_structure_to_tuple flat_structure_to_tuple] ]
|
||||
][
|
||||
[ [pfr_quick_examples_structure_tie] ]
|
||||
[ `var == {A, {1, 2.0}}` ]
|
||||
[ [funcref boost::pfr::structure_tie structure_tie] ]
|
||||
][
|
||||
[ [pfr_quick_examples_flat_structure_tie] ]
|
||||
[ `var == {C, {777, 3.14159}}` ]
|
||||
[ [funcref boost::pfr::flat_structure_tie flat_structure_tie] ]
|
||||
]]
|
||||
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
[section Tutorial]
|
||||
|
||||
[section Accessing POD member by index] [pfr_example_get] [endsect]
|
||||
[section Accessing structure member by index] [pfr_example_get] [endsect]
|
||||
[section Flattening] [pfr_example_flattening] [pfr_example_flattening_2] [endsect]
|
||||
[/ [section Counting fields] [pfr_example_tuple_size] [endsect] ]
|
||||
|
||||
[section Flat or Precise functions to choose]
|
||||
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.
|
||||
All the functions that have `flat_` prefix and are declared in `boost/pfr/flat/*` headers are 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.
|
||||
|
||||
* If you wish types flattened - use [*flat] functions
|
||||
* If you use types with C arrays - use [*flat] functions
|
||||
* Otherwise use [*precise] functions
|
||||
Use [*flat] functions if you:
|
||||
|
||||
* wish types flattened
|
||||
* or you reflect types with C arrays
|
||||
|
||||
For all the other cases prefer [*precise] functions.
|
||||
|
||||
[warning MSVC currently supports only [*precise] functions and only in /std:c++latest or /std:c++17 modes.]
|
||||
|
||||
@@ -78,7 +183,7 @@ There are three ways to start using Boost.PFR hashing, comparison and streaming
|
||||
|
||||
[table:flat_ops_comp Different approaches for operators
|
||||
[[ Approach
|
||||
][ Defines operators in global namespace ][ Defined operators could be found by ADL ][ Works for local types ][ Usable localy, without affecting code from other scopes ][ Ignores implicit conversion operators ][ Respects user defined operators ]]
|
||||
][ Defines operators in global namespace ][ Defined operators could be found by ADL ][ Works for local types ][ Usable locally, without affecting code from other scopes ][ Ignores implicit conversion operators ][ Respects user defined operators ]]
|
||||
|
||||
[[
|
||||
[headerref boost/pfr/precise/ops.hpp using\u00A0namespace\u00A0boost::pfr::ops;]
|
||||
@@ -138,7 +243,7 @@ struct uniform_comparator_less {
|
||||
|
||||
[*2. [macroref BOOST_PFR_FLAT_FUNCTIONS_FOR] and [macroref BOOST_PFR_PRECISE_FUNCTIONS_FOR] approach]
|
||||
|
||||
This method is good if you're writing POD structure and wish to define operators for that structure.
|
||||
This method is good if you're writing a structure and wish to define operators for that structure.
|
||||
```
|
||||
#include <boost/pfr/flat/functions_for.hpp>
|
||||
|
||||
@@ -186,7 +291,7 @@ struct pair_like {
|
||||
assert(pair_like{1, 2} < pair_like{1, 3});
|
||||
```
|
||||
Argument Dependant Lookup works well, `std::less` will find the operators for `struct pair_like`. Operators for local types will be also defined.
|
||||
*All conversion operators of all POD types won't be used during comparisons/streaming/hashing.*
|
||||
*All conversion operators of types are not used during comparisons/streaming/hashing.*
|
||||
|
||||
[endsect]
|
||||
|
||||
@@ -229,104 +334,6 @@ error: static_assert failed "====================> Boost.PFR: For safety reasons
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
[section Short Examples for the Impatient]
|
||||
|
||||
[import ../example/quick_examples.cpp]
|
||||
|
||||
[pfr_quick_examples_structures]
|
||||
|
||||
Following examples use definition from above:
|
||||
|
||||
[table:quick_examples
|
||||
[[ Code snippet ] [ `var` content or output ] [ Function description: ]]
|
||||
[
|
||||
[ [pfr_quick_examples_flat_functors_uset] ]
|
||||
[ `my_uset` constains `var` ]
|
||||
[
|
||||
[classref boost::pfr::flat_hash flat_hash]
|
||||
|
||||
[classref boost::pfr::flat_equal_to flat_equal_to]
|
||||
]
|
||||
][
|
||||
[ [pfr_quick_examples_flat_functors_set] ]
|
||||
[ `my_set` constains `var` ]
|
||||
[ [classref boost::pfr::flat_less flat_less] ]
|
||||
][
|
||||
[ [pfr_quick_examples_flat_ops] ]
|
||||
[ assert succeeds ]
|
||||
[ [headerref boost/pfr/flat/ops.hpp using\u00A0namespace\u00A0flat_ops;] ]
|
||||
][
|
||||
[ [pfr_quick_examples_ops] ]
|
||||
[ assert succeeds ]
|
||||
[ [headerref boost/pfr/precise/ops.hpp using\u00A0namespace\u00A0ops;] ]
|
||||
][
|
||||
[ [pfr_quick_examples_flat_for_each] ]
|
||||
[ `var == {B, {778, 4.14159}}` ]
|
||||
[ [funcref boost::pfr::flat_for_each_field flat_for_each_field] ]
|
||||
][
|
||||
[ [pfr_quick_examples_for_each] ]
|
||||
[ `var == {B, {787, 103.142}}` ]
|
||||
[ [funcref boost::pfr::for_each_field for_each_field] ]
|
||||
][
|
||||
[ [pfr_quick_examples_flat_for_each_idx] ]
|
||||
[ ```0: char
|
||||
1: int
|
||||
2: double
|
||||
``` ]
|
||||
[ [funcref boost::pfr::flat_for_each_field flat_for_each_field] ]
|
||||
][
|
||||
[ [pfr_quick_examples_for_each_idx] ]
|
||||
[ ```0: char
|
||||
1: quick_examples_ns::foo
|
||||
``` ]
|
||||
[ [funcref boost::pfr::for_each_field for_each_field] ]
|
||||
][
|
||||
[ [pfr_quick_examples_tuple_size] ]
|
||||
[ `tuple_size: 2` ]
|
||||
[ [classref boost::pfr::tuple_size tuple_size] ]
|
||||
][
|
||||
[ [pfr_quick_examples_flat_tuple_size] ]
|
||||
[ `flat_tuple_size: 3` ]
|
||||
[ [classref boost::pfr::flat_tuple_size flat_tuple_size] ]
|
||||
][
|
||||
[ [pfr_quick_examples_get_1] ]
|
||||
[ `var == {A {1, 2.0}}` ]
|
||||
[ [funcref boost::pfr::get get] ]
|
||||
][
|
||||
[ [pfr_quick_examples_flat_get_1] ]
|
||||
[ `var == {A, {1, 3.14159}}` ]
|
||||
[ [funcref boost::pfr::flat_get flat_get] ]
|
||||
][
|
||||
[ [pfr_quick_examples_get_2] ]
|
||||
[ `var == {A, {777, 42.01}}` ]
|
||||
[ [funcref boost::pfr::get get] ]
|
||||
][
|
||||
[ [pfr_quick_examples_flat_get_2] ]
|
||||
[ `var == {A, {777, 42.01}}` ]
|
||||
[ [funcref boost::pfr::flat_get flat_get] ]
|
||||
][
|
||||
[ [pfr_quick_examples_structure_to_tuple] ]
|
||||
[ `var == {A, {777, 3.14159}}` ]
|
||||
[ [funcref boost::pfr::structure_to_tuple structure_to_tuple] ]
|
||||
][
|
||||
[ [pfr_quick_examples_flat_structure_to_tuple] ]
|
||||
[ `var == {A, {777, 3.14159}}` ]
|
||||
[ [funcref boost::pfr::flat_structure_to_tuple flat_structure_to_tuple] ]
|
||||
][
|
||||
[ [pfr_quick_examples_structure_tie] ]
|
||||
[ `var == {A, {1, 2.0}}` ]
|
||||
[ [funcref boost::pfr::structure_tie structure_tie] ]
|
||||
][
|
||||
[ [pfr_quick_examples_flat_structure_tie] ]
|
||||
[ `var == {C, {777, 3.14159}}` ]
|
||||
[ [funcref boost::pfr::flat_structure_tie flat_structure_tie] ]
|
||||
]]
|
||||
|
||||
|
||||
[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:
|
||||
@@ -334,36 +341,30 @@ By default Boost.PFR [*auto-detects your compiler abilities] and automatically d
|
||||
[[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.]]
|
||||
[[*BOOST_PFR_USE_STD_MAKE_INTEGRAL_SEQUENCE*] [Define to `0` if you are hit by the template instantiation depth issues with `std::make_integer_sequence` and wish to use PFR version of that metafunction. Define to `1` otherwize. ]]
|
||||
]
|
||||
|
||||
Note that disabling [*Loophole] in C++14 significantly limitates the reflection abilities of the library. See next section for more info.
|
||||
Note that disabling [*Loophole] in C++14 significantly limits the reflection abilities of the library. See next section for more info.
|
||||
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
[section Requirements and Limitations]
|
||||
[section Limitations]
|
||||
|
||||
[note Boost.PFR does not depend on any Boost library. You may use it's headers even without Boost. ]
|
||||
The reflection has some limitations that depend on a C++ Standard and compiler capabilities:
|
||||
|
||||
* Boost.PFR *requires C++14 compatible compiler* (GCC-5.0+, Clang, ...)
|
||||
* Static variables are ignored
|
||||
* T must be aggregate initializable
|
||||
|
||||
[*Flat] functions limitations:
|
||||
|
||||
* T must be POD and must not contain references nor bitfields
|
||||
* Enums will be returned as their underlying type
|
||||
|
||||
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
|
||||
|
||||
|
||||
[*C++14] limitation (C++17 fixes those):
|
||||
|
||||
* Non of the member fields has a template constructor from one parameter
|
||||
* Additional C++14 [*only] limitations (switch to C++17 to remove all of those):
|
||||
* Non of the member fields should have a template constructor from one parameter.
|
||||
* Additional limitations if the [*Loophole] as also disabled:
|
||||
* [*Flat]:
|
||||
* T must be POD and must not contain references nor bitfields
|
||||
* Enums will be returned as their underlying type
|
||||
* [*Precise]:
|
||||
* 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
|
||||
|
||||
[endsect]
|
||||
|
||||
@@ -373,7 +374,7 @@ Short description:
|
||||
|
||||
* Flat functions:
|
||||
# at compile-time: use aggregate initialization to detect fields count in user-provided structure
|
||||
# at compile-time: make a structure that is convertible to anything and remeber types it has been converted to during aggregate initialization of user-provided structure
|
||||
# at compile-time: make a structure that is convertible to anything and remember types it has been converted to during aggregate initialization of user-provided structure
|
||||
# at compile-time: using knowledge from previous steps create a tuple with exactly the same layout as in user-provided structure
|
||||
# at compile-time: find offsets for each field in user-provided structure using the tuple from previous step
|
||||
# at run-time: get pointer to each field, knowing the structure address and each field offset
|
||||
|
||||
@@ -147,7 +147,7 @@ void test_examples() {
|
||||
{
|
||||
bar var{'A', {777, 3.141593}};
|
||||
//[pfr_quick_examples_get_1
|
||||
boost::pfr::get<1>(var) = foo{1, 2}; // C++17 is required
|
||||
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';
|
||||
}
|
||||
@@ -182,7 +182,7 @@ void test_examples() {
|
||||
{
|
||||
bar var{'A', {777, 3.141593}};
|
||||
//[pfr_quick_examples_structure_to_tuple
|
||||
// C++17 is required
|
||||
// C++17 or Loophole is required
|
||||
std::tuple<char, foo> t = boost::pfr::structure_to_tuple(var);
|
||||
std::get<1>(t) = foo{1, 2};
|
||||
//]
|
||||
@@ -203,7 +203,7 @@ void test_examples() {
|
||||
{
|
||||
bar var{'A', {777, 3.141593}};
|
||||
//[pfr_quick_examples_structure_tie
|
||||
// C++17 is required
|
||||
// C++17 or Loophole is required
|
||||
std::tuple<char&, foo&> t = boost::pfr::structure_tie(var);
|
||||
std::get<1>(t) = foo{1, 2};
|
||||
//]
|
||||
|
||||
@@ -49,4 +49,15 @@
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(__has_cpp_attribute)
|
||||
# if __has_cpp_attribute(maybe_unused)
|
||||
# define BOOST_PFR_MAYBE_UNUSED [[maybe_unused]]
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_PFR_MAYBE_UNUSED
|
||||
# define BOOST_PFR_MAYBE_UNUSED
|
||||
#endif
|
||||
|
||||
|
||||
#endif // BOOST_PFR_DETAIL_CONFIG_HPP
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <boost/pfr/detail/make_flat_tuple_of_references.hpp>
|
||||
#include <boost/pfr/detail/make_integer_sequence.hpp>
|
||||
#include <boost/pfr/detail/size_array.hpp>
|
||||
#include <boost/pfr/detail/size_t_.hpp>
|
||||
#include <boost/pfr/detail/rvalue_t.hpp>
|
||||
|
||||
#ifdef __clang__
|
||||
@@ -32,10 +33,7 @@ namespace boost { namespace pfr { namespace detail {
|
||||
|
||||
///////////////////// General utility stuff
|
||||
|
||||
template <std::size_t Index>
|
||||
using size_t_ = std::integral_constant<std::size_t, Index >;
|
||||
|
||||
template <class T> struct identity{
|
||||
template <class T> struct identity {
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include <boost/pfr/detail/make_integer_sequence.hpp>
|
||||
#include <boost/pfr/detail/sequence_tuple.hpp>
|
||||
#include <boost/pfr/detail/rvalue_t.hpp>
|
||||
#include <boost/pfr/detail/unsafe_declval.hpp>
|
||||
|
||||
|
||||
#ifdef __clang__
|
||||
@@ -59,12 +60,6 @@ struct tag {
|
||||
friend auto loophole(tag<T,N>);
|
||||
};
|
||||
|
||||
// For returning non default constructible types. Never used at runtime! GCC's std::declval may not be used in potentionally evaluated contexts, so it does not work here.
|
||||
template <class T> constexpr T& unsafe_declval_like() noexcept {
|
||||
T* ptr = nullptr;
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
// The definitions of friend functions.
|
||||
template <class T, class U, std::size_t N, bool B>
|
||||
struct fn_def_lref {
|
||||
@@ -75,13 +70,13 @@ struct fn_def_lref {
|
||||
// To workaround the issue, we check that the type U is movable, and move it in that case.
|
||||
using no_extents_t = std::remove_all_extents_t<U>;
|
||||
return static_cast< std::conditional_t<std::is_move_constructible<no_extents_t>::value, no_extents_t&&, no_extents_t&> >(
|
||||
boost::pfr::detail::unsafe_declval_like<no_extents_t>()
|
||||
boost::pfr::detail::unsafe_declval<no_extents_t&>()
|
||||
);
|
||||
}
|
||||
};
|
||||
template <class T, class U, std::size_t N, bool B>
|
||||
struct fn_def_rref {
|
||||
friend auto loophole(tag<T,N>) { return std::move(boost::pfr::detail::unsafe_declval_like< std::remove_all_extents_t<U> >()); }
|
||||
friend auto loophole(tag<T,N>) { return std::move(boost::pfr::detail::unsafe_declval< std::remove_all_extents_t<U>& >()); }
|
||||
};
|
||||
|
||||
|
||||
@@ -193,7 +188,7 @@ decltype(auto) tie_or_value(T& val, std::enable_if_t<std::is_enum<std::remove_re
|
||||
}
|
||||
|
||||
template <class T>
|
||||
auto tie_or_value(T& val, std::enable_if_t<std::is_union< std::remove_reference_t<T> >::value>* = 0) noexcept {
|
||||
auto tie_or_value(T& /*val*/, std::enable_if_t<std::is_union< std::remove_reference_t<T> >::value>* = 0) noexcept {
|
||||
static_assert(
|
||||
sizeof(T) && false,
|
||||
"====================> Boost.PFR: For safety reasons it is forbidden to reflect unions. See `Reflection of unions` section in the docs for more info."
|
||||
|
||||
@@ -1024,6 +1024,12 @@ constexpr auto tie_as_tuple(T& val, size_t_<100>) noexcept {
|
||||
}
|
||||
|
||||
|
||||
template <class T, std::size_t I>
|
||||
constexpr void tie_as_tuple(T& val, size_t_<I>) noexcept {
|
||||
static_assert(sizeof(T) && false,
|
||||
"====================> Boost.PFR: Too many fields in a structure T. Regenerate include/boost/pfr/detail/core17_generated.hpp file for appropriate count of fields. For example: `python ./misc/generate_cpp17.py 300 > include/boost/pfr/detail/core17_generated.hpp`");
|
||||
}
|
||||
|
||||
}}} // namespace boost::pfr::detail
|
||||
|
||||
#endif // BOOST_PFR_DETAIL_CORE17_GENERATED_HPP
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
|
||||
#include <boost/pfr/detail/config.hpp>
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost { namespace pfr { namespace detail {
|
||||
///////////////////// `value` is true if Detector<Tleft, Tright> does not compile (SFINAE)
|
||||
struct success{};
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <boost/pfr/detail/config.hpp>
|
||||
#include <boost/pfr/detail/make_integer_sequence.hpp>
|
||||
#include <boost/pfr/detail/size_t_.hpp>
|
||||
#include <boost/pfr/detail/unsafe_declval.hpp>
|
||||
|
||||
#include <climits> // CHAR_BIT
|
||||
#include <type_traits>
|
||||
@@ -28,13 +29,17 @@ namespace boost { namespace pfr { namespace detail {
|
||||
///////////////////// Structure that can be converted to reference to anything
|
||||
struct ubiq_lref_constructor {
|
||||
std::size_t ignore;
|
||||
template <class Type> /*constexpr*/ operator Type&() const noexcept; // Undefined, allows initialization of reference fields (T& and const T&)
|
||||
template <class Type> constexpr operator Type&() const noexcept { // Allows initialization of reference fields (T& and const T&)
|
||||
return detail::unsafe_declval<Type&>();
|
||||
};
|
||||
};
|
||||
|
||||
///////////////////// Structure that can be converted to rvalue reference to anything
|
||||
struct ubiq_rref_constructor {
|
||||
std::size_t ignore;
|
||||
template <class Type> /*constexpr*/ operator Type&&() const noexcept; // Undefined, allows initialization of rvalue reference fields and move-only types
|
||||
template <class Type> /*constexpr*/ operator Type&&() const noexcept { // Allows initialization of rvalue reference fields and move-only types
|
||||
return detail::unsafe_declval<Type&&>();
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
||||
36
include/boost/pfr/detail/unsafe_declval.hpp
Normal file
36
include/boost/pfr/detail/unsafe_declval.hpp
Normal file
@@ -0,0 +1,36 @@
|
||||
// Copyright (c) 2019-2020 Antony Polukhin.
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_PFR_DETAIL_UNSAFE_DECLVAL_HPP
|
||||
#define BOOST_PFR_DETAIL_UNSAFE_DECLVAL_HPP
|
||||
|
||||
#include <boost/pfr/detail/config.hpp>
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost { namespace pfr { namespace detail {
|
||||
|
||||
// This function serves as a link-time assert. If linker requires it, then
|
||||
// `unsafe_declval()` is used at runtime.
|
||||
void report_if_you_see_link_error_with_this_function() noexcept;
|
||||
|
||||
// For returning non default constructible types. Do NOT use at runtime!
|
||||
//
|
||||
// GCC's std::declval may not be used in potentionally evaluated contexts,
|
||||
// so we reinvent it.
|
||||
template <class T>
|
||||
constexpr T unsafe_declval() noexcept {
|
||||
report_if_you_see_link_error_with_this_function();
|
||||
|
||||
typename std::remove_reference<T>::type* ptr = 0;
|
||||
ptr += 42; // suppresses 'null pointer dereference' warnings
|
||||
return static_cast<T>(*ptr);
|
||||
}
|
||||
|
||||
}}} // namespace boost::pfr::detail
|
||||
|
||||
|
||||
#endif // BOOST_PFR_DETAIL_UNSAFE_DECLVAL_HPP
|
||||
|
||||
@@ -54,26 +54,26 @@
|
||||
/// std::size_t hash_value(const T& value) noexcept;
|
||||
/// \endcode
|
||||
|
||||
#define BOOST_PFR_FLAT_FUNCTIONS_FOR(T) \
|
||||
static inline bool operator==(const T& lhs, const T& rhs) noexcept { return ::boost::pfr::flat_equal_to<T>{}(lhs, rhs); } \
|
||||
static inline bool operator!=(const T& lhs, const T& rhs) noexcept { return ::boost::pfr::flat_not_equal<T>{}(lhs, rhs); } \
|
||||
static inline bool operator< (const T& lhs, const T& rhs) noexcept { return ::boost::pfr::flat_less<T>{}(lhs, rhs); } \
|
||||
static inline bool operator> (const T& lhs, const T& rhs) noexcept { return ::boost::pfr::flat_greater<T>{}(lhs, rhs); } \
|
||||
static inline bool operator<=(const T& lhs, const T& rhs) noexcept { return ::boost::pfr::flat_less_equal<T>{}(lhs, rhs); } \
|
||||
static inline bool operator>=(const T& lhs, const T& rhs) noexcept { return ::boost::pfr::flat_greater_equal<T>{}(lhs, rhs); } \
|
||||
template <class Char, class Traits> \
|
||||
static ::std::basic_ostream<Char, Traits>& operator<<(::std::basic_ostream<Char, Traits>& out, const T& value) { \
|
||||
::boost::pfr::flat_write(out, value); \
|
||||
return out; \
|
||||
} \
|
||||
template <class Char, class Traits> \
|
||||
static ::std::basic_istream<Char, Traits>& operator>>(::std::basic_istream<Char, Traits>& in, T& value) { \
|
||||
::boost::pfr::flat_read(in, value); \
|
||||
return in; \
|
||||
} \
|
||||
static inline std::size_t hash_value(const T& v) noexcept { \
|
||||
return ::boost::pfr::flat_hash<T>{}(v); \
|
||||
} \
|
||||
#define BOOST_PFR_FLAT_FUNCTIONS_FOR(T) \
|
||||
BOOST_PFR_MAYBE_UNUSED static inline bool operator==(const T& lhs, const T& rhs) noexcept { return ::boost::pfr::flat_equal_to<T>{}(lhs, rhs); } \
|
||||
BOOST_PFR_MAYBE_UNUSED static inline bool operator!=(const T& lhs, const T& rhs) noexcept { return ::boost::pfr::flat_not_equal<T>{}(lhs, rhs); } \
|
||||
BOOST_PFR_MAYBE_UNUSED static inline bool operator< (const T& lhs, const T& rhs) noexcept { return ::boost::pfr::flat_less<T>{}(lhs, rhs); } \
|
||||
BOOST_PFR_MAYBE_UNUSED static inline bool operator> (const T& lhs, const T& rhs) noexcept { return ::boost::pfr::flat_greater<T>{}(lhs, rhs); } \
|
||||
BOOST_PFR_MAYBE_UNUSED static inline bool operator<=(const T& lhs, const T& rhs) noexcept { return ::boost::pfr::flat_less_equal<T>{}(lhs, rhs); } \
|
||||
BOOST_PFR_MAYBE_UNUSED static inline bool operator>=(const T& lhs, const T& rhs) noexcept { return ::boost::pfr::flat_greater_equal<T>{}(lhs, rhs); } \
|
||||
template <class Char, class Traits> \
|
||||
BOOST_PFR_MAYBE_UNUSED static ::std::basic_ostream<Char, Traits>& operator<<(::std::basic_ostream<Char, Traits>& out, const T& value) { \
|
||||
::boost::pfr::flat_write(out, value); \
|
||||
return out; \
|
||||
} \
|
||||
template <class Char, class Traits> \
|
||||
BOOST_PFR_MAYBE_UNUSED static ::std::basic_istream<Char, Traits>& operator>>(::std::basic_istream<Char, Traits>& in, T& value) { \
|
||||
::boost::pfr::flat_read(in, value); \
|
||||
return in; \
|
||||
} \
|
||||
BOOST_PFR_MAYBE_UNUSED static inline std::size_t hash_value(const T& v) noexcept { \
|
||||
return ::boost::pfr::flat_hash<T>{}(v); \
|
||||
} \
|
||||
/**/
|
||||
|
||||
#endif // BOOST_PFR_FLAT_FUNCTIONS_FOR_HPP
|
||||
|
||||
@@ -52,26 +52,26 @@
|
||||
/// std::size_t hash_value(const T& value);
|
||||
/// \endcode
|
||||
|
||||
#define BOOST_PFR_PRECISE_FUNCTIONS_FOR(T) \
|
||||
static inline bool operator==(const T& lhs, const T& rhs) { return ::boost::pfr::equal_to<T>{}(lhs, rhs); } \
|
||||
static inline bool operator!=(const T& lhs, const T& rhs) { return ::boost::pfr::not_equal<T>{}(lhs, rhs); } \
|
||||
static inline bool operator< (const T& lhs, const T& rhs) { return ::boost::pfr::less<T>{}(lhs, rhs); } \
|
||||
static inline bool operator> (const T& lhs, const T& rhs) { return ::boost::pfr::greater<T>{}(lhs, rhs); } \
|
||||
static inline bool operator<=(const T& lhs, const T& rhs) { return ::boost::pfr::less_equal<T>{}(lhs, rhs); } \
|
||||
static inline bool operator>=(const T& lhs, const T& rhs) { return ::boost::pfr::greater_equal<T>{}(lhs, rhs); } \
|
||||
template <class Char, class Traits> \
|
||||
static ::std::basic_ostream<Char, Traits>& operator<<(::std::basic_ostream<Char, Traits>& out, const T& value) { \
|
||||
::boost::pfr::write(out, value); \
|
||||
return out; \
|
||||
} \
|
||||
template <class Char, class Traits> \
|
||||
static ::std::basic_istream<Char, Traits>& operator>>(::std::basic_istream<Char, Traits>& in, T& value) { \
|
||||
::boost::pfr::read(in, value); \
|
||||
return in; \
|
||||
} \
|
||||
static inline std::size_t hash_value(const T& v) { \
|
||||
return ::boost::pfr::hash<T>{}(v); \
|
||||
} \
|
||||
#define BOOST_PFR_PRECISE_FUNCTIONS_FOR(T) \
|
||||
BOOST_PFR_MAYBE_UNUSED static inline bool operator==(const T& lhs, const T& rhs) { return ::boost::pfr::equal_to<T>{}(lhs, rhs); } \
|
||||
BOOST_PFR_MAYBE_UNUSED static inline bool operator!=(const T& lhs, const T& rhs) { return ::boost::pfr::not_equal<T>{}(lhs, rhs); } \
|
||||
BOOST_PFR_MAYBE_UNUSED static inline bool operator< (const T& lhs, const T& rhs) { return ::boost::pfr::less<T>{}(lhs, rhs); } \
|
||||
BOOST_PFR_MAYBE_UNUSED static inline bool operator> (const T& lhs, const T& rhs) { return ::boost::pfr::greater<T>{}(lhs, rhs); } \
|
||||
BOOST_PFR_MAYBE_UNUSED static inline bool operator<=(const T& lhs, const T& rhs) { return ::boost::pfr::less_equal<T>{}(lhs, rhs); } \
|
||||
BOOST_PFR_MAYBE_UNUSED static inline bool operator>=(const T& lhs, const T& rhs) { return ::boost::pfr::greater_equal<T>{}(lhs, rhs); } \
|
||||
template <class Char, class Traits> \
|
||||
BOOST_PFR_MAYBE_UNUSED static ::std::basic_ostream<Char, Traits>& operator<<(::std::basic_ostream<Char, Traits>& out, const T& value) { \
|
||||
::boost::pfr::write(out, value); \
|
||||
return out; \
|
||||
} \
|
||||
template <class Char, class Traits> \
|
||||
BOOST_PFR_MAYBE_UNUSED static ::std::basic_istream<Char, Traits>& operator>>(::std::basic_istream<Char, Traits>& in, T& value) { \
|
||||
::boost::pfr::read(in, value); \
|
||||
return in; \
|
||||
} \
|
||||
BOOST_PFR_MAYBE_UNUSED static inline std::size_t hash_value(const T& v) { \
|
||||
return ::boost::pfr::hash<T>{}(v); \
|
||||
} \
|
||||
/**/
|
||||
|
||||
#endif // BOOST_PFR_PRECISE_FUNCTIONS_FOR_HPP
|
||||
|
||||
@@ -64,22 +64,18 @@ constexpr auto tie_as_tuple(T& val, size_t_<1>, std::enable_if_t<!std::is_class<
|
||||
|
||||
############################################################################################################################
|
||||
EPILOGUE = """
|
||||
template <class T, std::size_t I>
|
||||
constexpr void tie_as_tuple(T& val, size_t_<I>) noexcept {
|
||||
static_assert(sizeof(T) && false,
|
||||
"====================> Boost.PFR: Too many fields in a structure T. Regenerate include/boost/pfr/detail/core17_generated.hpp file for appropriate count of fields. For example: `python ./misc/generate_cpp17.py 300 > include/boost/pfr/detail/core17_generated.hpp`");
|
||||
}
|
||||
|
||||
}}} // namespace boost::pfr::detail
|
||||
|
||||
#endif // BOOST_PFR_DETAIL_CORE17_GENERATED_HPP
|
||||
"""
|
||||
|
||||
############################################################################################################################
|
||||
generate_sfinae_attempts = False
|
||||
|
||||
|
||||
if generate_sfinae_attempts:
|
||||
print """
|
||||
template <class T, std::size_t I>
|
||||
constexpr auto tie_as_tuple(T& val, size_t_<I>) noexcept {
|
||||
return tie_as_tuple(val, size_t_<I - 1>{});
|
||||
}
|
||||
"""
|
||||
|
||||
|
||||
indexes = " a"
|
||||
@@ -112,10 +108,4 @@ for i in xrange(1, funcs_count):
|
||||
|
||||
print "}\n"
|
||||
|
||||
if generate_sfinae_attempts:
|
||||
print "template <class T>"
|
||||
print "constexpr auto tie_as_tuple(T& val, size_t_<" + str(i + 1) + "> v) noexcept"
|
||||
print " ->decltype( ::boost::pfr::detail::tie_as_tuple0(std::forward<T>(val), v) )"
|
||||
print "{ return ::boost::pfr::detail::tie_as_tuple0(std::forward<T>(val), v); }\n"
|
||||
|
||||
print EPILOGUE
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2016-2019, Antony Polukhin.
|
||||
# Copyright (C) 2016-2020, Antony Polukhin.
|
||||
#
|
||||
# Use, modification and distribution is subject to the Boost Software License,
|
||||
# Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@@ -143,6 +143,7 @@ test-suite pfr
|
||||
[ run precise/destructuring_tie.cpp : : : $(CLASSIC_PREC_DEF) : precise_destructuring_tie ]
|
||||
[ run precise/error_pfr_c1202.cpp : : : $(CLASSIC_PREC_DEF) : precise_c1202_issue21 ]
|
||||
[ compile-fail precise/non_aggregate.cpp : $(CLASSIC_PREC_DEF) : precise_non_aggregate ]
|
||||
[ run precise/tie_anonymous.cpp : : : $(CLASSIC_PREC_DEF) [ requires cxx17_structured_bindings ] : precise_tie_anonymous ]
|
||||
|
||||
# See "Requirements and Limitations" section of the docs for info on following tests:
|
||||
#[ compile-fail precise/template_constructor.cpp : $(CLASSIC_PREC_DEF) [ requires !cxx17_structured_bindings ] : precise_template_constructor14 ]
|
||||
@@ -176,6 +177,7 @@ test-suite pfr
|
||||
[ run precise/issue30.cpp : : : $(LOOPHOLE_PREC_DEF) : precise_lh_issue30 ]
|
||||
[ run precise/issue33.cpp : : : $(LOOPHOLE_PREC_DEF) : precise_lh_issue33 ]
|
||||
[ compile-fail precise/non_aggregate.cpp : $(LOOPHOLE_PREC_DEF) : precise_lh_non_aggregate ]
|
||||
[ run precise/tie_anonymous.cpp : : : $(LOOPHOLE_PREC_DEF) [ requires cxx17_structured_bindings ] : precise_lh_tie_anonymous ]
|
||||
|
||||
# See "Requirements and Limitations" section of the docs for info on following tests:
|
||||
#[ compile-fail precise/template_constructor.cpp : $(LOOPHOLE_PREC_DEF) [ requires !cxx17_structured_bindings ] : precise_lh_template_constructor14 ]
|
||||
|
||||
@@ -39,10 +39,11 @@ struct comparable_struct {
|
||||
|
||||
BOOST_PFR_TEST_FUNCTIONS_FOR(comparable_struct)
|
||||
|
||||
void test_comparable_struct() {
|
||||
comparable_struct s1 {0, 1, false, 6,7,8,9,10,11};
|
||||
comparable_struct s2 = s1;
|
||||
comparable_struct s3 {0, 1, false, 6,7,8,9,10,11111};
|
||||
template <typename Struct>
|
||||
void test_some_comparable_struct() {
|
||||
Struct s1 {0, 1, false, 6,7,8,9,10,11};
|
||||
Struct s2 = s1;
|
||||
Struct s3 {0, 1, false, 6,7,8,9,10,11111};
|
||||
BOOST_TEST_EQ(s1, s2);
|
||||
BOOST_TEST(s1 <= s2);
|
||||
BOOST_TEST(s1 >= s2);
|
||||
@@ -56,7 +57,7 @@ void test_comparable_struct() {
|
||||
|
||||
std::cout << s1 << std::endl;
|
||||
|
||||
comparable_struct s4;
|
||||
Struct s4;
|
||||
std::stringstream ss;
|
||||
ss.exceptions ( std::ios::failbit);
|
||||
ss << s1;
|
||||
@@ -67,6 +68,10 @@ void test_comparable_struct() {
|
||||
BOOST_TEST_NE(i, j);
|
||||
}
|
||||
|
||||
void test_comparable_struct() {
|
||||
test_some_comparable_struct<comparable_struct>();
|
||||
}
|
||||
|
||||
struct empty { operator std::string() { return "empty{}"; } };
|
||||
BOOST_PFR_TEST_FUNCTIONS_FOR(empty)
|
||||
|
||||
@@ -105,12 +110,58 @@ void test_implicit_conversions() {
|
||||
BOOST_TEST_EQ(ss.str(), "{}"); // Breaks implicit conversion for types marked with BOOST_PFR_TEST_FUNCTIONS_FOR
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
struct anonymous_comparable_struct {
|
||||
int i; short s; bool bl; int a,b,c,d,e,f;
|
||||
};
|
||||
|
||||
BOOST_PFR_TEST_FUNCTIONS_FOR(anonymous_comparable_struct)
|
||||
|
||||
|
||||
struct other_anonymous_struct {
|
||||
anonymous_comparable_struct a,b;
|
||||
};
|
||||
|
||||
BOOST_PFR_TEST_FUNCTIONS_FOR(other_anonymous_struct)
|
||||
|
||||
}
|
||||
|
||||
namespace std {
|
||||
template <>
|
||||
struct hash<anonymous_comparable_struct> {
|
||||
std::size_t operator()(const anonymous_comparable_struct& val) const noexcept {
|
||||
return hash_value(val);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
void test_anonymous_comparable_struct() {
|
||||
test_some_comparable_struct<anonymous_comparable_struct>();
|
||||
}
|
||||
|
||||
void test_nested_anonymous_comparable_struct() {
|
||||
other_anonymous_struct s1{
|
||||
{0, 1, false, 6,7,8,9,10,11},
|
||||
{0, 1, false, 6,7,8,9,10,11},
|
||||
};
|
||||
auto s2 = s1;
|
||||
|
||||
BOOST_TEST_EQ(s1, s2);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int main() {
|
||||
test_comparable_struct();
|
||||
test_empty_struct();
|
||||
test_with_contatiners<std::less<>>();
|
||||
test_with_contatiners<std::greater<>>();
|
||||
test_implicit_conversions();
|
||||
test_anonymous_comparable_struct();
|
||||
test_nested_anonymous_comparable_struct();
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2018 Antony Polukhin
|
||||
// Copyright (c) 2018-2020 Antony Polukhin
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
@@ -122,7 +122,5 @@ void test_counts_on_multiple_chars() {
|
||||
|
||||
int main() {
|
||||
test_counts_on_multiple_chars< BOOST_PFR_RUN_TEST_ON >();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ struct non_default_constructible {
|
||||
T val_;
|
||||
|
||||
non_default_constructible() = delete;
|
||||
template <class U> non_default_constructible(U&& v){}
|
||||
template <class U> non_default_constructible(U&& /*v*/){}
|
||||
};
|
||||
|
||||
struct Foo {
|
||||
|
||||
@@ -11,7 +11,7 @@ struct optional_like {
|
||||
T val_;
|
||||
|
||||
optional_like() = default;
|
||||
template <class U> optional_like(U&& v){}
|
||||
template <class U> optional_like(U&& /*v*/){}
|
||||
};
|
||||
|
||||
struct Foo {
|
||||
|
||||
94
test/precise/tie_anonymous.cpp
Normal file
94
test/precise/tie_anonymous.cpp
Normal file
@@ -0,0 +1,94 @@
|
||||
// Copyright (c) 2020 Antony Polukhin
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
|
||||
#include <boost/pfr/precise/ops.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
#if defined(__has_include)
|
||||
# if __has_include(<optional>)
|
||||
# include <optional>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
namespace some {
|
||||
struct struct1{ int i; };
|
||||
struct struct2{ int i; };
|
||||
}
|
||||
|
||||
namespace testing {
|
||||
|
||||
namespace {
|
||||
|
||||
#ifdef __cpp_lib_optional
|
||||
struct anon_with_optional {
|
||||
std::string a;
|
||||
std::optional<some::struct1> b;
|
||||
std::optional<some::struct2> c;
|
||||
|
||||
};
|
||||
|
||||
struct other_anon_with_optional {
|
||||
std::string a;
|
||||
int b;
|
||||
std::optional<anon_with_optional> c;
|
||||
std::optional<some::struct2> d;
|
||||
|
||||
};
|
||||
#endif
|
||||
|
||||
struct other_anon {
|
||||
int data;
|
||||
};
|
||||
|
||||
struct anon {
|
||||
other_anon a;
|
||||
other_anon b;
|
||||
};
|
||||
|
||||
void test_in_anon_ns() {
|
||||
anon x{{1}, {2}};
|
||||
|
||||
auto v = boost::pfr::structure_tie(x);
|
||||
|
||||
BOOST_TEST_EQ(std::get<0>(v).data, 1);
|
||||
BOOST_TEST_EQ(std::get<1>(v).data, 2);
|
||||
|
||||
#ifdef __cpp_lib_optional
|
||||
other_anon_with_optional opt{"test", {}, {}, {}};
|
||||
auto opt_val = boost::pfr::structure_tie(opt);
|
||||
BOOST_TEST_EQ(std::get<0>(opt_val), "test");
|
||||
#endif
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
void test_in_non_non_ns() {
|
||||
anon x{{1}, {2}};
|
||||
|
||||
auto v = boost::pfr::structure_tie(x);
|
||||
|
||||
BOOST_TEST_EQ(std::get<0>(v).data, 1);
|
||||
BOOST_TEST_EQ(std::get<1>(v).data, 2);
|
||||
|
||||
#ifdef __cpp_lib_optional
|
||||
other_anon_with_optional opt{"test again", {}, {}, {}};
|
||||
auto opt_val = boost::pfr::structure_tie(opt);
|
||||
BOOST_TEST_EQ(std::get<0>(opt_val), "test again");
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace testing
|
||||
|
||||
int main() {
|
||||
testing::test_in_anon_ns();
|
||||
testing::test_in_non_non_ns();
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user