diff --git a/doc/Jamfile.v2 b/doc/Jamfile.v2
index 5fd85d4..e0bbe39 100644
--- a/doc/Jamfile.v2
+++ b/doc/Jamfile.v2
@@ -33,6 +33,8 @@ local doxygen_params =
\"flattening{1}=\\xmlonly\\1\\endxmlonly\" \\
\"podops=\\b See \\b Also: \\xmlonlyThree ways of getting operators\\endxmlonly\" \\
\"constexprinit{1}=\\xmlonly\\1\\endxmlonly\" \\
+ \"rcast=\\b Misc: Reinterpret casts unrelated types.\" \\
+ \"rcast14=\\b Misc: Reinterpret casts unrelated types in C++14 only. May have overhead in C++14 only on non-optimizing compilers.\" \\
\"flatpod{1}=\\xmlonly\\1\\endxmlonly\" \\
"
;
diff --git a/doc/pfr.qbk b/doc/pfr.qbk
index cdc9814..b20e48f 100644
--- a/doc/pfr.qbk
+++ b/doc/pfr.qbk
@@ -23,7 +23,7 @@ This library provides tuple like methods for aggregate initializable structures,
No macro or other type/member registrations required.]
-Boost.Precise and Flat Reflection (Boost.PFR) adds following out-of-the-box functionality to PODs:
+Boost.Precise and Flat Reflection (Boost.PFR) adds following out-of-the-box functionality for aggregate initializable structures:
* comparison operators
* heterogeneous comparators
@@ -57,9 +57,9 @@ Precise functions have almost unlimited reflection capabilities, but may produce
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 work only with POD types in C++14 and wish them flattened - 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
[endsect]
@@ -74,15 +74,15 @@ There are three ways to start using Boost.PFR hashing, comparison and streaming
][ 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 ]]
[[
- [headerref boost/pfr/flat/ops.hpp]
+ [headerref boost/pfr/precise/ops.hpp using\u00A0namespace\u00A0boost::pfr::ops;]
- [headerref boost/pfr/precise/ops.hpp]
+ [headerref boost/pfr/flat/ops.hpp using\u00A0namespace\u00A0boost::pfr::flat_ops;]
][ no ][ no ][ yes ][ yes ][ no ][ yes ]]
[[
- [headerref boost/pfr/flat/functions_for.hpp]
+ [macroref BOOST_PFR_FLAT_FUNCTIONS_FOR]
- [headerref boost/pfr/precise/functions_for.hpp]
+ [macroref BOOST_PFR_PRECISE_FUNCTIONS_FOR]
][ yes if T is in it ][ yes ][ no ][ no, but could be limited to translation unit ][ yes for T ] [ no (compile time error) ]]
[[
@@ -92,9 +92,9 @@ There are three ways to start using Boost.PFR hashing, comparison and streaming
][ yes ][ yes ][ yes ][ no, but could be limited to translation unit ][ yes all ][ yes ]]
]
-More detailed description:
+More detailed description follows:
-[*1) [headerref boost/pfr/precise/ops.hpp] and [headerref boost/pfr/flat/ops.hpp] approach]
+[*1. [headerref boost/pfr/precise/ops.hpp `using namespace boost::pfr::ops;`] and [headerref boost/pfr/flat/ops.hpp `using namespace boost::pfr::flat_ops;`] approach]
This method is good if you're writing generic algorithms and need to use operators from Boost.PFR only if there's no operators defined for the type:
@@ -123,7 +123,7 @@ struct uniform_comparator_less {
};
```
-[*2) [headerref boost/pfr/flat/functions_for.hpp] approach]
+[*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.
```
@@ -156,7 +156,7 @@ struct empty {
std::cout << empty{}; // Outputs `empty{}` if BOOST_PFR_FLAT_FUNCTIONS_FOR(empty) is commented out, '{}' otherwise.
```
-[*3) [headerref boost/pfr/flat/global_ops.hpp] approach]
+[*3. [headerref boost/pfr/flat/global_ops.hpp] and [headerref boost/pfr/precise/global_ops.hpp] approach]
This approach is for those, who wish to have comparisons/streaming/hashing for all their types.
@@ -190,6 +190,26 @@ 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]
+
+ [classref boost::pfr::flat_equal_to]
+ ]
+][
+ [ [pfr_quick_examples_flat_functors_set] ]
+ [ `my_set` constains `var` ]
+ [ [classref boost::pfr::flat_less] ]
+][
+ [ [pfr_quick_examples_flat_ops] ]
+ [ assert succeeds ]
+ [ [headerref boost/pfr/flat/ops.hpp using\u00A0namespace\u00A0boost::pfr::flat_ops;] ]
+][
+ [ [pfr_quick_examples_ops] ]
+ [ assert succeeds ]
+ [ [headerref boost/pfr/precise/ops.hpp using\u00A0namespace\u00A0boost::pfr::ops;] ]
+][
[ [pfr_quick_examples_flat_for_each] ]
[ `var == {B, {778, 4.14159}}` ]
[ [funcref boost::pfr::flat_for_each_field] ]
diff --git a/example/examples.cpp b/example/examples.cpp
index a38093c..fee997f 100644
--- a/example/examples.cpp
+++ b/example/examples.cpp
@@ -101,6 +101,9 @@ assert(r == 11);
#include
#include
+#include
+#include
+#include
namespace quick_examples_ns {
@@ -131,6 +134,44 @@ void test_examples() {
{
bar var{'A', {777, 3.141593}};
+//[pfr_quick_examples_flat_functors_uset
+ // no `std::hash` or `bar::operator==(const bar&)` defined
+ std::unordered_set, boost::pfr::flat_equal_to<>> my_uset;
+ my_uset.insert(var);
+//]
+ }
+
+ {
+ bar var{'A', {777, 3.141593}};
+
+//[pfr_quick_examples_flat_functors_set
+ // no `bar::operator<(const bar&)` defined
+ std::set> my_set;
+ my_set.insert(var);
+//]
+ }
+
+ {
+//[pfr_quick_examples_flat_ops
+ using namespace boost::pfr::flat_ops; // Defines comparisons
+ assert((var < bar{'Z', {}} && var.f == foo{777, 3.141593}));
+//]
+ std::cout << "boost::pfr::flat_structure_tie(var) :\n" << var << '\n';
+ }
+
+#if __cplusplus >= 201606L /* Oulu meeting, not the exact value */
+ {
+//[pfr_quick_examples_ops
+ struct test { std::string f1; std::string_view f2; };
+ using namespace boost::pfr::ops; // Defines comparisons
+ assert((test{"abc", ""} > test{"aaa", "zomg"}));
+//]
+ }
+#endif
+
+ {
+ bar var{'A', {777, 3.141593}};
+
//[pfr_quick_examples_flat_for_each
// incrementing each field on 1:
boost::pfr::flat_for_each_field(var, [](auto& field) {
diff --git a/include/boost/pfr/flat/core.hpp b/include/boost/pfr/flat/core.hpp
index 8937805..24f9ed7 100644
--- a/include/boost/pfr/flat/core.hpp
+++ b/include/boost/pfr/flat/core.hpp
@@ -23,6 +23,8 @@ namespace boost { namespace pfr {
/// \brief Returns reference or const reference to a field with index `I` in \flattening{flattened} T.
///
+/// \rcast
+///
/// \b Example:
/// \code
/// struct my_struct { int i, short s; };
@@ -67,6 +69,8 @@ using flat_tuple_element_t = typename flat_tuple_element::type;
/// \brief Creates an `std::tuple` from a \flattening{flattened} T.
///
+/// \rcast
+///
/// \b Example:
/// \code
/// struct my_struct { int i, short s; };
@@ -85,6 +89,8 @@ auto flat_structure_to_tuple(const T& val) noexcept {
/// \brief Creates an `std::tuple` with lvalue references to fields of a \flattening{flattened} T.
///
+/// \rcast
+///
/// \b Requires: `T` must not have const fields.
///
/// \b Example:
@@ -104,10 +110,12 @@ auto flat_structure_tie(T& val /* @cond */, std::enable_if_t< std::is_trivially_
/// Calls `func` for each field of a \flattening{flattened} POD `value`.
///
+/// \rcast
+///
/// \param func must have one of the following signatures:
-/// * template any_return_type func(U&& field) // field of value is perfect forwarded to function
-/// * template any_return_type func(U&& field, std::size_t i)
-/// * template any_return_type func(U&& value, I i) // Here I is an `std::integral_constant`
+/// * any_return_type func(U&& field) // field of value is perfect forwarded to function
+/// * any_return_type func(U&& field, std::size_t i)
+/// * any_return_type func(U&& value, I i) // Here I is an `std::integral_constant`
///
/// \param value After \flattening{flattening} to each field of this variable will be the `func` applied.
///
diff --git a/include/boost/pfr/flat/functions_for.hpp b/include/boost/pfr/flat/functions_for.hpp
index cb472de..a9bcda9 100644
--- a/include/boost/pfr/flat/functions_for.hpp
+++ b/include/boost/pfr/flat/functions_for.hpp
@@ -33,6 +33,8 @@
/// std::cout << s1 << std::endl; // Outputs: {0, 1, H, e, l, l, o, , , 0, 6, 7, 8, 9, 10, 11}
/// \endcode
///
+/// \rcast
+///
/// \podops for other ways to define operators and more details.
///
/// \b Defines \b following \b for \b T:
diff --git a/include/boost/pfr/flat/functors.hpp b/include/boost/pfr/flat/functors.hpp
index 62bc827..222de6b 100644
--- a/include/boost/pfr/flat/functors.hpp
+++ b/include/boost/pfr/flat/functors.hpp
@@ -18,13 +18,17 @@
/// \file boost/pfr/functors.hpp
/// Contains functors that can work with PODs and are close to the Standard Library ones.
/// Each functor \flattening{flattens} the POD type and iterates over its fields.
+///
+/// \rcast
namespace boost { namespace pfr {
///////////////////// Comparisons
/// \brief std::equal_to like flattening comparator
template struct flat_equal_to {
- /// \return \b true if each field of \b x equals the field with same index of \b y
+ /// \return \b true if each field of \b x equals the field with same index of \b y.
+ ///
+ /// \rcast
bool operator()(const T& x, const T& y) const noexcept {
return detail::equal_impl<0, flat_tuple_size_v >::cmp(detail::tie_as_flat_tuple(x), detail::tie_as_flat_tuple(y));
}
@@ -54,7 +58,9 @@ template <> struct flat_equal_to {
/// \brief std::not_equal like flattening comparator
template struct flat_not_equal {
- /// \return \b true if at least one field \b x not equals the field with same index of \b y
+ /// \return \b true if at least one field \b x not equals the field with same index of \b y.
+ ///
+ /// \rcast
bool operator()(const T& x, const T& y) const noexcept {
return detail::not_equal_impl<0, flat_tuple_size_v >::cmp(detail::tie_as_flat_tuple(x), detail::tie_as_flat_tuple(y));
}
@@ -82,7 +88,9 @@ template <> struct flat_not_equal {
/// \brief std::greater like flattening comparator
template struct flat_greater {
- /// \return \b true if field of \b x greater than the field with same index of \b y and all previous fields of \b x equal to the same fields of \b y
+ /// \return \b true if field of \b x greater than the field with same index of \b y and all previous fields of \b x equal to the same fields of \b y.
+ ///
+ /// \rcast
bool operator()(const T& x, const T& y) const noexcept {
return detail::greater_impl<0, flat_tuple_size_v >::cmp(detail::tie_as_flat_tuple(x), detail::tie_as_flat_tuple(y));
}
@@ -113,7 +121,9 @@ template <> struct flat_greater {
/// \brief std::less like flattening comparator
template struct flat_less {
- /// \return \b true if field of \b x less than the field with same index of \b y and all previous fields of \b x equal to the same fields of \b y
+ /// \return \b true if field of \b x less than the field with same index of \b y and all previous fields of \b x equal to the same fields of \b y.
+ ///
+ /// \rcast
bool operator()(const T& x, const T& y) const noexcept {
return detail::less_impl<0, flat_tuple_size_v >::cmp(detail::tie_as_flat_tuple(x), detail::tie_as_flat_tuple(y));
}
@@ -145,7 +155,9 @@ template <> struct flat_less {
/// \brief std::greater_equal like flattening comparator
template struct flat_greater_equal {
/// \return \b true if field of \b x greater than the field with same index of \b y and all previous fields of \b x equal to the same fields of \b y;
- /// or if each field of \b x equals the field with same index of \b y .
+ /// or if each field of \b x equals the field with same index of \b y.
+ ///
+ /// \rcast
bool operator()(const T& x, const T& y) const noexcept {
return detail::greater_equal_impl<0, flat_tuple_size_v >::cmp(detail::tie_as_flat_tuple(x), detail::tie_as_flat_tuple(y));
}
@@ -177,7 +189,9 @@ template <> struct flat_greater_equal {
/// \brief std::less_equal like flattening comparator
template struct flat_less_equal {
/// \return \b true if field of \b x less than the field with same index of \b y and all previous fields of \b x equal to the same fields of \b y;
- /// or if each field of \b x equals the field with same index of \b y .
+ /// or if each field of \b x equals the field with same index of \b y.
+ ///
+ /// \rcast
bool operator()(const T& x, const T& y) const noexcept {
return detail::less_equal_impl<0, flat_tuple_size_v >::cmp(detail::tie_as_flat_tuple(x), detail::tie_as_flat_tuple(y));
}
@@ -209,7 +223,9 @@ template <> struct flat_less_equal {
/// \brief std::hash like flattening functor
template struct flat_hash {
- /// \return hash value of \b x
+ /// \return hash value of \b x.
+ ///
+ /// \rcast
std::size_t operator()(const T& x) const noexcept {
return detail::hash_impl<0, flat_tuple_size_v >::compute(detail::tie_as_flat_tuple(x));
}
diff --git a/include/boost/pfr/flat/global_ops.hpp b/include/boost/pfr/flat/global_ops.hpp
index f2c62ca..54e7b35 100644
--- a/include/boost/pfr/flat/global_ops.hpp
+++ b/include/boost/pfr/flat/global_ops.hpp
@@ -32,6 +32,8 @@
/// std::cout << s1 << std::endl; // Outputs: {0, 1, H, e, l, l, o, , , 0, 6, 7, 8, 9, 10, 11}
/// \endcode
///
+/// \rcast
+///
/// \podops for other ways to define operators and more details.
///
/// \b This \b header \b defines:
diff --git a/include/boost/pfr/flat/io.hpp b/include/boost/pfr/flat/io.hpp
index b2c0828..d9b0ea4 100644
--- a/include/boost/pfr/flat/io.hpp
+++ b/include/boost/pfr/flat/io.hpp
@@ -22,6 +22,8 @@ namespace boost { namespace pfr {
/// \brief Writes \flattening{flattened} POD `value` to `out`
///
+/// \rcast14
+///
/// \b Example:
/// \code
/// struct my_struct { int i, short s; };
@@ -37,6 +39,8 @@ void flat_write(std::basic_ostream& out, const T& value) {
/// Reads \flattening{flattened} POD `value` from stream `in`
///
+/// \rcast14
+///
/// \b Example:
/// \code
/// struct my_struct { int i, short s; };
diff --git a/include/boost/pfr/flat/ops.hpp b/include/boost/pfr/flat/ops.hpp
index ad3265c..0affc2b 100644
--- a/include/boost/pfr/flat/ops.hpp
+++ b/include/boost/pfr/flat/ops.hpp
@@ -36,6 +36,8 @@
/// std::cout << s1 << std::endl; // Outputs: {0, 1, H, e, l, l, o, , , 0, 6, 7, 8, 9, 10, 11}
/// \endcode
///
+/// \rcast
+///
/// \podops for other ways to define operators and more details.
///
/// \b This \b header \b contains:
diff --git a/include/boost/pfr/precise/core.hpp b/include/boost/pfr/precise/core.hpp
index 12f3b28..fa3e218 100644
--- a/include/boost/pfr/precise/core.hpp
+++ b/include/boost/pfr/precise/core.hpp
@@ -26,6 +26,8 @@ namespace boost { namespace pfr {
///
/// \b Requires: C++17 or \flatpod{C++14 flat POD}.
///
+/// \rcast14
+///
/// \b Example:
/// \code
/// struct my_struct { int i, short s; };
@@ -74,6 +76,8 @@ using tuple_element_t = typename tuple_element::type;
///
/// \b Requires: C++17 or \flatpod{C++14 flat POD}.
///
+/// \rcast14
+///
/// \b Example:
/// \code
/// struct my_struct { int i, short s; };
@@ -96,6 +100,8 @@ constexpr auto structure_to_tuple(const T& val) noexcept {
///
/// \b Requires: C++17 or \flatpod{C++14 flat POD}.
///
+/// \rcast14
+///
/// \b Example:
/// \code
/// struct my_struct { int i, short s; };
@@ -118,12 +124,14 @@ constexpr auto structure_tie(T& val) noexcept {
/// \b Requires: C++17 or \constexprinit{C++14 constexpr aggregate intializable type}.
///
/// \param func must have one of the following signatures:
-/// * template any_return_type func(U&& field) // field of value is perfect forwarded to function
-/// * template any_return_type func(U&& field, std::size_t i)
-/// * template any_return_type func(U&& value, I i) // Here I is an `std::integral_constant`
+/// * any_return_type func(U&& field) // field of value is perfect forwarded to function
+/// * any_return_type func(U&& field, std::size_t i)
+/// * any_return_type func(U&& value, I i) // Here I is an `std::integral_constant`
///
/// \param value To each field of this variable will be the `func` applied.
///
+/// \rcast14
+///
/// \b Example:
/// \code
/// struct my_struct { int i, short s; };
diff --git a/include/boost/pfr/precise/functions_for.hpp b/include/boost/pfr/precise/functions_for.hpp
index f1de098..19779a7 100644
--- a/include/boost/pfr/precise/functions_for.hpp
+++ b/include/boost/pfr/precise/functions_for.hpp
@@ -33,6 +33,8 @@
/// std::cout << s1 << std::endl; // Outputs: {0, 1, H, e, l, l, o, , , 0, 6, 7, 8, 9, 10, 11}
/// \endcode
///
+/// \rcast14
+///
/// \podops for other ways to define operators and more details.
///
/// \b Defines \b following \b for \b T:
diff --git a/include/boost/pfr/precise/functors.hpp b/include/boost/pfr/precise/functors.hpp
index bc00e15..09aa7f9 100644
--- a/include/boost/pfr/precise/functors.hpp
+++ b/include/boost/pfr/precise/functors.hpp
@@ -20,6 +20,8 @@
/// Each functor iterates over fields of the type.
///
/// \b Requires: C++17 or \constexprinit{C++14 constexpr aggregate intializable type}.
+///
+/// \rcast14
namespace boost { namespace pfr {
namespace detail {
@@ -59,7 +61,9 @@ namespace detail {
/// \brief std::equal_to like comparator
template struct equal_to {
- /// \return \b true if each field of \b x equals the field with same index of \b y
+ /// \return \b true if each field of \b x equals the field with same index of \b y.
+ ///
+ /// \rcast14
bool operator()(const T& x, const T& y) const {
return detail::binary_visit(x, y);
}
@@ -86,7 +90,9 @@ template <> struct equal_to {
/// \brief std::not_equal like comparator
template struct not_equal {
- /// \return \b true if at least one field \b x not equals the field with same index of \b y
+ /// \return \b true if at least one field \b x not equals the field with same index of \b y.
+ ///
+ /// \rcast14
bool operator()(const T& x, const T& y) const {
return detail::binary_visit(x, y);
}
@@ -114,7 +120,9 @@ template <> struct not_equal {
/// \brief std::greater like comparator
template struct greater {
- /// \return \b true if field of \b x greater than the field with same index of \b y and all previous fields of \b x equal to the same fields of \b y
+ /// \return \b true if field of \b x greater than the field with same index of \b y and all previous fields of \b x equal to the same fields of \b y.
+ ///
+ /// \rcast14
bool operator()(const T& x, const T& y) const {
return detail::binary_visit(x, y);
}
@@ -142,7 +150,9 @@ template <> struct greater {
/// \brief std::less like comparator
template struct less {
- /// \return \b true if field of \b x less than the field with same index of \b y and all previous fields of \b x equal to the same fields of \b y
+ /// \return \b true if field of \b x less than the field with same index of \b y and all previous fields of \b x equal to the same fields of \b y.
+ ///
+ /// \rcast14
bool operator()(const T& x, const T& y) const {
return detail::binary_visit(x, y);
}
@@ -171,7 +181,9 @@ template <> struct less {
/// \brief std::greater_equal like comparator
template struct greater_equal {
/// \return \b true if field of \b x greater than the field with same index of \b y and all previous fields of \b x equal to the same fields of \b y;
- /// or if each field of \b x equals the field with same index of \b y .
+ /// or if each field of \b x equals the field with same index of \b y.
+ ///
+ /// \rcast14
bool operator()(const T& x, const T& y) const {
return detail::binary_visit(x, y);
}
@@ -200,7 +212,9 @@ template <> struct greater_equal {
/// \brief std::less_equal like comparator
template struct less_equal {
/// \return \b true if field of \b x less than the field with same index of \b y and all previous fields of \b x equal to the same fields of \b y;
- /// or if each field of \b x equals the field with same index of \b y .
+ /// or if each field of \b x equals the field with same index of \b y.
+ ///
+ /// \rcast14
bool operator()(const T& x, const T& y) const {
return detail::binary_visit(x, y);
}
@@ -229,7 +243,9 @@ template <> struct less_equal {
/// \brief std::hash like functor
template struct hash {
- /// \return hash value of \b x
+ /// \return hash value of \b x.
+ ///
+ /// \rcast14
std::size_t operator()(const T& x) const {
constexpr std::size_t fields_count = detail::fields_count>();
#if __cplusplus >= 201606L /* Oulu meeting, not the exact value */
diff --git a/include/boost/pfr/precise/global_ops.hpp b/include/boost/pfr/precise/global_ops.hpp
index e3a7aad..fca1c44 100644
--- a/include/boost/pfr/precise/global_ops.hpp
+++ b/include/boost/pfr/precise/global_ops.hpp
@@ -32,6 +32,8 @@
/// std::cout << s1 << std::endl; // Outputs: {0, 1, H, e, l, l, o, , , 0, 6, 7, 8, 9, 10, 11}
/// \endcode
///
+/// \rcast14
+///
/// \podops for other ways to define operators and more details.
///
/// \b This \b header \b defines:
diff --git a/include/boost/pfr/precise/io.hpp b/include/boost/pfr/precise/io.hpp
index f638dc5..cf2a0b1 100644
--- a/include/boost/pfr/precise/io.hpp
+++ b/include/boost/pfr/precise/io.hpp
@@ -26,6 +26,8 @@ namespace boost { namespace pfr {
///
/// \b Requires: C++17 or \constexprinit{C++14 constexpr aggregate intializable type}.
///
+/// \rcast14
+///
/// \b Example:
/// \code
/// struct my_struct { int i, short s; };
@@ -54,6 +56,8 @@ void write(std::basic_ostream& out, const T& value) {
///
/// \b Requires: C++17 or \constexprinit{C++14 constexpr aggregate intializable type}.
///
+/// \rcast14
+///
/// \b Example:
/// \code
/// struct my_struct { int i, short s; };
diff --git a/include/boost/pfr/precise/ops.hpp b/include/boost/pfr/precise/ops.hpp
index f2979cb..c399e85 100644
--- a/include/boost/pfr/precise/ops.hpp
+++ b/include/boost/pfr/precise/ops.hpp
@@ -23,6 +23,8 @@
///
/// \b Requires: C++17 or \constexprinit{C++14 constexpr aggregate intializable type}.
///
+/// \rcast14
+///
/// \b Example:
/// \code
/// #include