diff --git a/README.md b/README.md index 176e5be..3cfee71 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,7 @@ This C++14 library is meant for accessing structure elements by index and provid [Latest documentation](http://apolukhin.github.com/magic_get/index.html) +[Pre Boost version](https://github.com/apolukhin/magic_get/tree/pre_boost) ### Motivating example @@ -31,7 +32,6 @@ my_struct has 3 fields: { 100, H, 3.14159 } ``` - ### Requirements and Limitations * C++14 compatible compiler (GCC-5.0+, Clang, ...) diff --git a/doc/Jamfile.v2 b/doc/Jamfile.v2 index 25faad5..e1a44ee 100644 --- a/doc/Jamfile.v2 +++ b/doc/Jamfile.v2 @@ -10,11 +10,7 @@ using doxygen ; doxygen autodoc : [ glob ../../../boost/pfr.hpp ] - [ glob ../../../boost/pfr/core.hpp ] - [ glob ../../../boost/pfr/functors.hpp ] - [ glob ../../../boost/pfr/pod_ops.hpp ] - [ glob ../../../boost/pfr/define_functions_for.hpp ] - [ glob ../../../boost/pfr/global_pod_ops.hpp ] + [ glob ../../../boost/pfr/*.hpp ] : EXTRACT_ALL=NO HIDE_UNDOC_MEMBERS=YES @@ -24,6 +20,10 @@ doxygen autodoc MACRO_EXPANSION=YES INLINE_SIMPLE_STRUCTS=YES SORT_MEMBER_DOCS=NO + "ALIASES= \\ + \"flattening{1}=\\xmlonly\\1\\endxmlonly\" \\ + \"podops=\\b See \\b Also: \\xmlonlyThree ways of getting operators\\endxmlonly\" \\ + " "PREDEFINED=\"BOOST_PFR_DOXYGEN_INVOKED\" \\ \"detail::stl_type_info=std::type_info\"" "boost.doxygen.reftitle=Boost.PFR Header Reference" diff --git a/doc/pfr.qbk b/doc/pfr.qbk index cf6d64a..5e1f6a9 100644 --- a/doc/pfr.qbk +++ b/doc/pfr.qbk @@ -35,23 +35,36 @@ Boost.POD Flat Reflection (Boost.PFR) adds following out-of-the-box functionalit [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!] -[warning This is a C++14 library! C++11, C++03, C++98 compilers are not supported] +[caution This is a C++14 library! Pre C++14 compilers (C++11, C++03...) are not supported] [endsect] -[section Getting Started] +[section Quick Start] [import ../example/examples.cpp] [section Accessing POD member by index] [pfr_example_get] [endsect] [section Flattening] [pfr_example_flattening] [pfr_example_flattening_2] [endsect] -[section Counting fields] [pfr_example_flat_tuple_size] [endsect] - +[/ [section Counting fields] [pfr_example_flat_tuple_size] [endsect] ] [section Three ways of getting operators ] -There are three ways to start using operators for type T in your code. Each method has it's own drawbacks and suits own cases. +There are three ways to start using Boost.PFR hashing, comparison and streaming operators for type `T` in your code. Each method has it's own drawbacks and suits own cases. -[*1) Approach with namespace pod_ops] +[table:pod_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 ] ] + [[ [headerref boost/pfr/pod_ops.hpp] ] [ no ] [ no ] [ yes ] [ yes ] [ no ] [ yes ] ] + [[ [headerref boost/pfr/define_functions_for.hpp] ] [ yes if T is in it ] [ yes ] [ no ] [ no, but could be limited to translation unit ] [ yes for T ] [ no (compile time error) ] ] + [[ [headerref boost/pfr/global_pod_ops.hpp] ] [ yes ] [ yes ] [ yes ] [ no, but could be limited to translation unit ] [ yes all ] [ yes ] ] +] + +More detailed description: + +[*1) [headerref boost/pfr/pod_ops.hpp] 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: @@ -61,12 +74,12 @@ This method is good if you're writing generic algorithms and need to use operato template struct uniform_comparator_less { bool operator()(const T& lhs, const T& rhs) const noexcept { - using namespace pod_ops; - return lhs < rhs; // if T has operator< or conversion operator then will use it, otherwise will use boost::pfr::flat_less + using namespace pod_ops; // Enables Boost.PFR operators usage in this scope. + return lhs < rhs; // If T has operator< or conversion operator then will use it, otherwise will use boost::pfr::flat_less. } }; ``` -This method does not change other code, it's effects are local to the function. It works even fro local types, like structures defined in functions. +This method's effects are local to the function. It works even for local types, like structures defined in functions. However *Argument Dependant Lookup* does not work with it: ``` @@ -75,12 +88,12 @@ template struct uniform_comparator_less { bool operator()(const T& lhs, const T& rhs) const noexcept { using namespace pod_ops; - return std::less{}(lhs, rhs); // compile time error if T has neither operator< nor conversion operator to comparable type. + return std::less{}(lhs, rhs); // Compile time error if T has neither operator< nor conversion operator to comparable type. } }; ``` -[*2) Approach with [macroref BOOST_PFR_DEFINE_FUNCTIONS_FOR] ] +[*2) [headerref boost/pfr/define_functions_for.hpp] approach] This method is good if you're writing POD structure and wish to define operators for that structure. ``` @@ -91,7 +104,7 @@ struct pair_like { short second; }; -BOOST_PFR_DEFINE_FUNCTIONS_FOR(pair_like) +BOOST_PFR_DEFINE_FUNCTIONS_FOR(pair_like) // Defines operators // ... @@ -113,9 +126,12 @@ struct empty { std::cout << empty{}; // Outputs `empty{}` if BOOST_PFR_DEFINE_FUNCTIONS_FOR(empty) is commented out, '{}' otherwise. ``` -[*3) Approach with [headerref boost/pfr/global_pod_ops.hpp] ] +[*3) [headerref boost/pfr/global_pod_ops.hpp] approach] + +This approach is for those, who wish to have comparisong/streaming/hashing for all their types. + ``` -#include +#include struct pair_like { int first; @@ -127,19 +143,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/streamin/hashing.* - -This approach is for those, who wish to have comparisong/streaming/hashing for all their types - -[section Table of approach differences ] -[table:pod_ops_comp Different approaches for operators - [[ Approach ] [ In Global namespace ] [ ADL works ] [ Works for local types ] [ Usable localy ] [ Breaks implicit conversion ] [ Respects defined operators ] ] - [[ `using namespace pod_ops;` ] [ no ] [ no ] [ yes ] [ yes ] [ no ] [ strongly ] ] - [[ BOOST_PFR_DEFINE_FUNCTIONS_FOR(T) ] [ yes if T in it ] [ yes ] [ no ] [ no ] [ yes for T ] [ no ] ] - [[ `global_pod_ops.hpp` ] [ yes ] [ yes ] [ yes ] [ no ] [ yes all ] [ yes ] ] -] -[endsect] - +*All conversion operators of all POD types won't be used during comparisons/streaming/hashing.* [endsect] @@ -159,6 +163,10 @@ This approach is for those, who wish to have comparisong/streaming/hashing for a * Fields of enum type will be returned as their underlying type * Static variables are ignored +[caution All the methods that provide access to filds have a `reinterpret_cast` to an unrelated type. All the possible efforts and compiler scpecific tricks were used to avoid issues. + +But strictly speaking *this is an Undefined Behavior.* ] + [endsect] [xinclude autodoc.xml] diff --git a/include/boost/pfr.hpp b/include/boost/pfr.hpp index e4acb15..f24ba63 100644 --- a/include/boost/pfr.hpp +++ b/include/boost/pfr.hpp @@ -5,6 +5,9 @@ #pragma once +/// \file boost/pfr.hpp +/// Includes all the Boost.PFR headers, except \xmlonlyboost/pfr/global_pod_ops.hpp\endxmlonly + #include #include #include diff --git a/include/boost/pfr/core.hpp b/include/boost/pfr/core.hpp index b8e16e7..1ddc6ef 100644 --- a/include/boost/pfr/core.hpp +++ b/include/boost/pfr/core.hpp @@ -679,11 +679,14 @@ struct teleport_extents { #endif /// @endcond -/// \brief Returns const reference to a field with index `I` in flattened `T`. +/// \brief Returns reference or const reference to a field with index `I` in \flattening{flattened} T. /// /// \b Example: /// \code -/// boost::pfr::get<0>(my_structure()); +/// struct my_struct { int i, short s; }; +/// my_struct s {10, 11}; +/// assert(boost::pfr::get<0>(s) == 10); +/// boost::pfr::get<1>(s) = 0; /// \endcode template decltype(auto) get(const T& val) noexcept { @@ -700,7 +703,7 @@ decltype(auto) get(T& val /* @cond */, std::enable_if_t< std::is_trivially_assig } -/// \brief `flat_tuple_element` has a `typedef type-of-a-field-with-index-I-in-flattened-T type;` +/// \brief `flat_tuple_element` has a `typedef type-of-a-field-with-index-I-in-\flattening{flattened}-T type;` /// /// \b Example: /// \code @@ -713,7 +716,7 @@ using flat_tuple_element = detail::teleport_extents< >; -/// \brief Type of a field with index `I` in flattened `T` +/// \brief Type of a field with index `I` in \flattening{flattened} `T` /// /// \b Example: /// \code @@ -723,7 +726,7 @@ template using flat_tuple_element_t = typename flat_tuple_element::type; -/// \brief has a member `value` that constins fields count in a flattened `T`. +/// \brief has a member `value` that constins fields count in a \flattening{flattened} T. /// /// \b Example: /// \code @@ -733,7 +736,7 @@ template using flat_tuple_size = detail::size_t_< detail::as_tuple_t::size_v >; -/// \brief `flat_tuple_size_v` is a template variable that constins fields count in a flattened `T`. +/// \brief `flat_tuple_size_v` is a template variable that constins fields count in a \flattening{flattened} T. /// /// \b Example: /// \code @@ -743,7 +746,7 @@ template constexpr std::size_t flat_tuple_size_v = flat_tuple_size::value; -/// \brief Creates an `std::tuple` from a flattened T. +/// \brief Creates an `std::tuple` from a \flattening{flattened} T. /// /// \b Example: /// \code @@ -763,7 +766,7 @@ auto flat_make_tuple(const T& val) noexcept { } -/// \brief Creates an `std::tuple` with lvalue references to fields of a flattened T. +/// \brief Creates an `std::tuple` with lvalue references to fields of a \flattening{flattened} T. /// /// \b Requires: `T` must not have const fields. /// @@ -804,7 +807,7 @@ namespace detail { }; } -/// \brief Writes to `out` the POD `value` +/// \brief Writes \flattening{flattened} POD `value` to `out` /// /// \b Example: /// \code @@ -843,7 +846,7 @@ namespace detail { }; } -/// Reads POD `value` from stream `in` +/// Reads \flattening{flattened} POD `value` from stream `in` /// /// \b Example: /// \code diff --git a/include/boost/pfr/define_functions_for.hpp b/include/boost/pfr/define_functions_for.hpp index 763b9fd..6207409 100644 --- a/include/boost/pfr/define_functions_for.hpp +++ b/include/boost/pfr/define_functions_for.hpp @@ -11,16 +11,18 @@ #include -/// \file boost/pfr/global_pod_ops.hpp -/// Contains comparison operators and stream operators for any POD types that do not have their own operators. -/// If POD is comparable or streamable using it's own operator or it's conversion operator, then the original operator is used. +/// \def BOOST_PFR_DEFINE_FUNCTIONS_FOR(T) +/// Defines comparison operators and stream operators for T. +/// If POD is comparable or streamable using it's own operator (but not it's conversion operator), then the original operator is used. /// /// \b Example: /// \code +/// #include /// struct comparable_struct { // No operators defined for that structure /// int i; short s; char data[7]; bool bl; int a,b,c,d,e,f; /// }; -/// using namespace pod_ops; +/// BOOST_PFR_DEFINE_FUNCTIONS_FOR(comparable_struct) +/// // ... /// /// comparable_struct s1 {0, 1, "Hello", false, 6,7,8,9,10,11}; /// comparable_struct s2 {0, 1, "Hello", false, 6,7,8,9,10,11111}; @@ -28,29 +30,47 @@ /// std::cout << s1 << std::endl; // Outputs: {0, 1, H, e, l, l, o, , , 0, 6, 7, 8, 9, 10, 11} /// \endcode /// -/// \see boost/pfr/global_pod_ops.hpp for a more aggressive way to define operators. +/// \podops for other ways to define operators and more details. +/// +/// \b Defines \b following \b for \b T: +/// \code +/// bool operator==(const T& lhs, const T& rhs) noexcept; +/// bool operator!=(const T& lhs, const T& rhs) noexcept; +/// bool operator< (const T& lhs, const T& rhs) noexcept; +/// bool operator> (const T& lhs, const T& rhs) noexcept; +/// bool operator<=(const T& lhs, const T& rhs) noexcept; +/// bool operator>=(const T& lhs, const T& rhs) noexcept; +/// +/// template +/// std::basic_ostream& operator<<(std::basic_ostream& out, const T& value); +/// +/// template +/// std::basic_istream& operator>>(std::basic_istream& in, T& value); +/// +/// // helper function for Boost unordered containers and boost::hash<>. +/// std::size_t hash_value(const T& value) noexcept; +/// \endcode - -#define BOOST_PFR_DEFINE_FUNCTIONS_FOR(T) \ - inline bool operator==(const T& lhs, const T& rhs) noexcept { return ::boost::pfr::flat_equal_to{}(lhs, rhs); } \ - inline bool operator!=(const T& lhs, const T& rhs) noexcept { return ::boost::pfr::flat_not_equal{}(lhs, rhs); } \ - inline bool operator< (const T& lhs, const T& rhs) noexcept { return ::boost::pfr::flat_less{}(lhs, rhs); } \ - inline bool operator> (const T& lhs, const T& rhs) noexcept { return ::boost::pfr::flat_greater{}(lhs, rhs); } \ - inline bool operator<=(const T& lhs, const T& rhs) noexcept { return ::boost::pfr::flat_less_equal{}(lhs, rhs); } \ - inline bool operator>=(const T& lhs, const T& rhs) noexcept { return ::boost::pfr::flat_greater_equal{}(lhs, rhs); } \ - template \ - ::std::basic_ostream& operator<<(::std::basic_ostream& out, const T& value) { \ - ::boost::pfr::flat_write(out, value); \ - return out; \ - } \ - template \ - ::std::basic_istream& operator>>(::std::basic_istream& in, T& value) { \ - ::boost::pfr::flat_read(in, value); \ - return in; \ - } \ - std::size_t hash_value(const T& v) noexcept { \ - return ::boost::pfr::flat_hash{}(v); \ - } \ +#define BOOST_PFR_DEFINE_FUNCTIONS_FOR(T) \ + static inline bool operator==(const T& lhs, const T& rhs) noexcept { return ::boost::pfr::flat_equal_to{}(lhs, rhs); } \ + static inline bool operator!=(const T& lhs, const T& rhs) noexcept { return ::boost::pfr::flat_not_equal{}(lhs, rhs); } \ + static inline bool operator< (const T& lhs, const T& rhs) noexcept { return ::boost::pfr::flat_less{}(lhs, rhs); } \ + static inline bool operator> (const T& lhs, const T& rhs) noexcept { return ::boost::pfr::flat_greater{}(lhs, rhs); } \ + static inline bool operator<=(const T& lhs, const T& rhs) noexcept { return ::boost::pfr::flat_less_equal{}(lhs, rhs); } \ + static inline bool operator>=(const T& lhs, const T& rhs) noexcept { return ::boost::pfr::flat_greater_equal{}(lhs, rhs); } \ + template \ + static ::std::basic_ostream& operator<<(::std::basic_ostream& out, const T& value) { \ + ::boost::pfr::flat_write(out, value); \ + return out; \ + } \ + template \ + static ::std::basic_istream& operator>>(::std::basic_istream& 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{}(v); \ + } \ /**/ diff --git a/include/boost/pfr/functors.hpp b/include/boost/pfr/functors.hpp index 5d5d817..8565bd0 100644 --- a/include/boost/pfr/functors.hpp +++ b/include/boost/pfr/functors.hpp @@ -11,6 +11,10 @@ #include +/// \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. + namespace boost { namespace pfr { namespace detail { @@ -49,7 +53,7 @@ namespace detail { }; template - inline void hash_combine(SizeT& seed, SizeT value) noexcept { + constexpr void hash_combine(SizeT& seed, SizeT value) noexcept { seed ^= value + 0x9e3779b9 + (seed<<6) + (seed>>2); } @@ -75,17 +79,28 @@ namespace detail { constexpr std::size_t min_size(std::size_t x, std::size_t y) noexcept { return x < y ? x : y; } -} +} // namespace detail ///////////////////// Comparisons -/// flat_equal_to<> +/// \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 bool operator()(const T& x, const T& y) const noexcept { return detail::equal_impl<0, flat_tuple_size_v >::cmp(x, y); } + +#ifdef BOOST_PFR_DOXYGEN_INVOKED + /// This typedef exists only if T \b is void + typedef std::true_type is_transparent; + + /// This operator allows comparison of \b x and \b y that have different type. + /// \pre Exists only if T \b is void. + template bool operator()(const V& x, const U& y) const noexcept; +#endif }; +/// @cond template <> struct flat_equal_to { template bool operator()(const T& x, const U& y) const noexcept { @@ -95,16 +110,27 @@ template <> struct flat_equal_to { >::cmp(x, y); } - typedef std::true_type is_transparent; }; +/// @endcond -/// flat_not_equal<> +/// \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 bool operator()(const T& x, const T& y) const noexcept { return !flat_equal_to{}(x, y); } + +#ifdef BOOST_PFR_DOXYGEN_INVOKED + /// This typedef exists only if T \b is void + typedef std::true_type is_transparent; + + /// This operator allows comparison of \b x and \b y that have different type. + /// \pre Exists only if T \b is void. + template bool operator()(const V& x, const U& y) const noexcept; +#endif }; +/// @cond template <> struct flat_not_equal { template bool operator()(const T& x, const U& y) const noexcept { @@ -113,14 +139,26 @@ template <> struct flat_not_equal { typedef std::true_type is_transparent; }; +/// @endcond -/// flat_greater<> +/// \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 eqeal to the same fields of \b y bool operator()(const T& x, const T& y) const noexcept { return detail::less_impl<0, flat_tuple_size_v >::cmp(y, x); } + +#ifdef BOOST_PFR_DOXYGEN_INVOKED + /// This typedef exists only if T \b is void + typedef std::true_type is_transparent; + + /// This operator allows comparison of \b x and \b y that have different type. + /// \pre Exists only if T \b is void. + template bool operator()(const V& x, const U& y) const noexcept; +#endif }; +/// @cond template <> struct flat_greater { template bool operator()(const T& x, const U& y) const noexcept { @@ -132,14 +170,26 @@ template <> struct flat_greater { typedef std::true_type is_transparent; }; +/// @endcond -/// flat_less<> +/// \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 eqeal to the same fields of \b y bool operator()(const T& x, const T& y) const noexcept { return detail::less_impl<0, flat_tuple_size_v >::cmp(x, y); } + +#ifdef BOOST_PFR_DOXYGEN_INVOKED + /// This typedef exists only if T \b is void + typedef std::true_type is_transparent; + + /// This operator allows comparison of \b x and \b y that have different type. + /// \pre Exists only if T \b is void. + template bool operator()(const V& x, const U& y) const noexcept; +#endif }; +/// @cond template <> struct flat_less { template bool operator()(const T& x, const U& y) const noexcept { @@ -151,14 +201,27 @@ template <> struct flat_less { typedef std::true_type is_transparent; }; +/// @endcond -/// flat_greater_equal<> +/// \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 eqeal to the same fields of \b y; + /// or if each field of \b x equals the field with same index of \b y . bool operator()(const T& x, const T& y) const noexcept { return !flat_less{}(x, y); } + +#ifdef BOOST_PFR_DOXYGEN_INVOKED + /// This typedef exists only if T \b is void + typedef std::true_type is_transparent; + + /// This operator allows comparison of \b x and \b y that have different type. + /// \pre Exists only if T \b is void. + template bool operator()(const V& x, const U& y) const noexcept; +#endif }; +/// @cond template <> struct flat_greater_equal { template bool operator()(const T& x, const U& y) const noexcept { @@ -167,14 +230,27 @@ template <> struct flat_greater_equal { typedef std::true_type is_transparent; }; +/// @endcond -/// flat_less_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 eqeal to the same fields of \b y; + /// or if each field of \b x equals the field with same index of \b y . bool operator()(const T& x, const T& y) const noexcept { return !flat_greater{}(x, y); } + +#ifdef BOOST_PFR_DOXYGEN_INVOKED + /// This typedef exists only if T \b is void + typedef std::true_type is_transparent; + + /// This operator allows comparison of \b x and \b y that have different type. + /// \pre Exists only if T \b is void. + template bool operator()(const V& x, const U& y) const noexcept; +#endif }; +/// @cond template <> struct flat_less_equal { template bool operator()(const T& x, const U& y) const noexcept { @@ -183,9 +259,12 @@ template <> struct flat_less_equal { typedef std::true_type is_transparent; }; +/// @endcond -/// flat_hash + +/// \brief std::hash like flattening functor template struct flat_hash { + /// \return hash value of \b x std::size_t operator()(const T& x) const noexcept { return detail::hash_impl<0, flat_tuple_size_v >::compute(x); } diff --git a/include/boost/pfr/global_pod_ops.hpp b/include/boost/pfr/global_pod_ops.hpp index 3cc75bf..38bc539 100644 --- a/include/boost/pfr/global_pod_ops.hpp +++ b/include/boost/pfr/global_pod_ops.hpp @@ -11,6 +11,28 @@ #include +/// \file boost/pfr/global_pod_ops.hpp +/// Contains comparison operators and stream operators for any POD types that do not have their own operators. +/// If POD is comparable or streamable using it's own operator (but not it's conversion operator), then the original operator is used. +/// +/// \b Example: +/// \code +/// #include +/// struct comparable_struct { // No operators defined for that structure +/// int i; short s; char data[7]; bool bl; int a,b,c,d,e,f; +/// }; +/// // ... +/// +/// comparable_struct s1 {0, 1, "Hello", false, 6,7,8,9,10,11}; +/// comparable_struct s2 {0, 1, "Hello", false, 6,7,8,9,10,11111}; +/// assert(s1 < s2); +/// std::cout << s1 << std::endl; // Outputs: {0, 1, H, e, l, l, o, , , 0, 6, 7, 8, 9, 10, 11} +/// \endcode +/// +/// \podops for other ways to define operators and more details. +/// +/// \b This \b header \b defines: +/// @cond namespace boost { namespace pfr { namespace detail { template @@ -20,6 +42,7 @@ namespace boost { namespace pfr { namespace detail { >; }}} // namespace boost::pfr::detail +/// @endcond #ifdef BOOST_PFR_DOXYGEN_INVOKED template bool operator==(const T& lhs, const T& rhs) noexcept; @@ -35,7 +58,7 @@ namespace boost { namespace pfr { namespace detail { template std::basic_istream& operator>>(std::basic_istream& in, T& value); - /// \brief helper function for Boost + /// \brief helper function for Boost unordered containers and boost::hash<>. template std::size_t hash_value(const T& value) noexcept; #else template diff --git a/include/boost/pfr/pod_ops.hpp b/include/boost/pfr/pod_ops.hpp index 83826b4..387f294 100644 --- a/include/boost/pfr/pod_ops.hpp +++ b/include/boost/pfr/pod_ops.hpp @@ -15,11 +15,16 @@ /// Contains comparison operators and stream operators for any POD types that do not have their own operators. /// If POD is comparable or streamable using it's own operator or it's conversion operator, then the original operator is used. /// +/// Just write \b using \b namespace \b pod_ops; and operators will be available in scope. +/// /// \b Example: /// \code +/// #include /// struct comparable_struct { // No operators defined for that structure /// int i; short s; char data[7]; bool bl; int a,b,c,d,e,f; /// }; +/// // ... +/// /// using namespace pod_ops; /// /// comparable_struct s1 {0, 1, "Hello", false, 6,7,8,9,10,11}; @@ -28,8 +33,9 @@ /// std::cout << s1 << std::endl; // Outputs: {0, 1, H, e, l, l, o, , , 0, 6, 7, 8, 9, 10, 11} /// \endcode /// -/// \see BOOST_PFR_DEFINE_FUNCTIONS_FOR(T) for a more aggressive way to define operators. - +/// \podops for other ways to define operators and more details. +/// +/// \b This \b header \b contains: namespace boost { namespace pfr { namespace detail { diff --git a/test/test_counts_on.hpp b/test/test_counts_on.hpp index 00da8d0..c273d14 100644 --- a/test/test_counts_on.hpp +++ b/test/test_counts_on.hpp @@ -6,7 +6,7 @@ #ifndef BOOST_PFR_TEST_TEST_COUNTS_ON_HPP #define BOOST_PFR_TEST_TEST_COUNTS_ON_HPP -#include +#include template void test_counts_on_multiple_chars_impl_1() {