Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-16 08:42:25

0001 // Copyright (c) 2016-2025 Antony Polukhin
0002 //
0003 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0004 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0005 
0006 #ifndef BOOST_PFR_CORE_HPP
0007 #define BOOST_PFR_CORE_HPP
0008 #pragma once
0009 
0010 #include <boost/pfr/detail/config.hpp>
0011 
0012 #include <boost/pfr/detail/core.hpp>
0013 
0014 #include <boost/pfr/detail/sequence_tuple.hpp>
0015 #include <boost/pfr/detail/stdtuple.hpp>
0016 #include <boost/pfr/detail/for_each_field.hpp>
0017 #include <boost/pfr/detail/make_integer_sequence.hpp>
0018 #include <boost/pfr/detail/tie_from_structure_tuple.hpp>
0019 
0020 #include <type_traits>
0021 #include <utility>      // metaprogramming stuff
0022 
0023 #include <boost/pfr/tuple_size.hpp>
0024 
0025 /// \file boost/pfr/core.hpp
0026 /// Contains all the basic tuple-like interfaces \forcedlink{get}, \forcedlink{tuple_size}, \forcedlink{tuple_element_t}, and others.
0027 ///
0028 /// \b Synopsis:
0029 
0030 namespace boost { namespace pfr {
0031 
0032 BOOST_PFR_BEGIN_MODULE_EXPORT
0033 
0034 /// \brief Returns reference or const reference to a field with index `I` in \aggregate `val`.
0035 /// Overload taking the type `U` returns reference or const reference to a field
0036 /// with provided type `U` in \aggregate `val` if there's only one field of such type in `val`.
0037 ///
0038 /// \b Example:
0039 /// \code
0040 ///     struct my_struct { int i, short s; };
0041 ///     my_struct s {10, 11};
0042 ///
0043 ///     assert(boost::pfr::get<0>(s) == 10);
0044 ///     boost::pfr::get<1>(s) = 0;
0045 ///
0046 ///     assert(boost::pfr::get<int>(s) == 10);
0047 ///     boost::pfr::get<short>(s) = 11;
0048 /// \endcode
0049 template <std::size_t I, class T>
0050 constexpr decltype(auto) get(const T& val) noexcept {
0051     return detail::sequence_tuple::get<I>( detail::tie_as_tuple(val) );
0052 }
0053 
0054 /// \overload get
0055 template <std::size_t I, class T>
0056 constexpr decltype(auto) get(T& val
0057 #if !BOOST_PFR_USE_CPP17
0058     , std::enable_if_t<std::is_assignable<T, T>::value>* = nullptr
0059 #endif
0060 ) noexcept {
0061     return detail::sequence_tuple::get<I>( detail::tie_as_tuple(val) );
0062 }
0063 
0064 #if !BOOST_PFR_USE_CPP17
0065 /// \overload get
0066 template <std::size_t I, class T>
0067 constexpr auto get(T&, std::enable_if_t<!std::is_assignable<T, T>::value>* = nullptr) noexcept {
0068     static_assert(sizeof(T) && false, "====================> Boost.PFR: Calling boost::pfr::get on non const non assignable type is allowed only in C++17");
0069     return 0;
0070 }
0071 #endif
0072 
0073 
0074 /// \overload get
0075 template <std::size_t I, class T>
0076 constexpr auto get(T&& val, std::enable_if_t< std::is_rvalue_reference<T&&>::value>* = nullptr) noexcept {
0077     return std::move(detail::sequence_tuple::get<I>( detail::tie_as_tuple(val) ));
0078 }
0079 
0080 
0081 /// \overload get
0082 template <class U, class T>
0083 constexpr const U& get(const T& val) noexcept {
0084     return detail::sequence_tuple::get_by_type_impl<const U&>( detail::tie_as_tuple(val) );
0085 }
0086 
0087 
0088 /// \overload get
0089 template <class U, class T>
0090 constexpr U& get(T& val
0091 #if !BOOST_PFR_USE_CPP17
0092     , std::enable_if_t<std::is_assignable<T, T>::value>* = nullptr
0093 #endif
0094 ) noexcept {
0095     return detail::sequence_tuple::get_by_type_impl<U&>( detail::tie_as_tuple(val) );
0096 }
0097 
0098 #if !BOOST_PFR_USE_CPP17
0099 /// \overload get
0100 template <class U, class T>
0101 constexpr U& get(T&, std::enable_if_t<!std::is_assignable<T, T>::value>* = nullptr) noexcept {
0102     static_assert(sizeof(T) && false, "====================> Boost.PFR: Calling boost::pfr::get on non const non assignable type is allowed only in C++17");
0103     return 0;
0104 }
0105 #endif
0106 
0107 
0108 /// \overload get
0109 template <class U, class T>
0110 constexpr U&& get(T&& val, std::enable_if_t< std::is_rvalue_reference<T&&>::value>* = nullptr) noexcept {
0111     return std::move(detail::sequence_tuple::get_by_type_impl<U&>( detail::tie_as_tuple(val) ));
0112 }
0113 
0114 
0115 /// \brief `tuple_element` has a member typedef `type` that returns the type of a field with index I in \aggregate T.
0116 ///
0117 /// \b Example:
0118 /// \code
0119 ///     std::vector< boost::pfr::tuple_element<0, my_structure>::type > v;
0120 /// \endcode
0121 template <std::size_t I, class T>
0122 using tuple_element = detail::sequence_tuple::tuple_element<I, decltype( ::boost::pfr::detail::tie_as_tuple(std::declval<T&>()) ) >;
0123 
0124 
0125 /// \brief Type of a field with index `I` in \aggregate `T`.
0126 ///
0127 /// \b Example:
0128 /// \code
0129 ///     std::vector< boost::pfr::tuple_element_t<0, my_structure> > v;
0130 /// \endcode
0131 template <std::size_t I, class T>
0132 using tuple_element_t = typename tuple_element<I, T>::type;
0133 
0134 
0135 /// \brief Creates a `std::tuple` from fields of an \aggregate `val`.
0136 ///
0137 /// \b Example:
0138 /// \code
0139 ///     struct my_struct { int i, short s; };
0140 ///     my_struct s {10, 11};
0141 ///     std::tuple<int, short> t = boost::pfr::structure_to_tuple(s);
0142 ///     assert(get<0>(t) == 10);
0143 /// \endcode
0144 template <class T>
0145 constexpr auto structure_to_tuple(const T& val) {
0146     return detail::make_stdtuple_from_tietuple(
0147         detail::tie_as_tuple(val),
0148         detail::make_index_sequence< tuple_size_v<T> >()
0149     );
0150 }
0151 
0152 
0153 /// \brief std::tie` like function that ties fields of a structure.
0154 ///
0155 /// \returns a `std::tuple` with lvalue and const lvalue references to fields of an \aggregate `val`.
0156 ///
0157 /// \b Example:
0158 /// \code
0159 ///     void foo(const int&, const short&);
0160 ///     struct my_struct { int i, short s; };
0161 ///
0162 ///     const my_struct const_s{1, 2};
0163 ///     std::apply(foo, boost::pfr::structure_tie(const_s));
0164 ///
0165 ///     my_struct s;
0166 ///     boost::pfr::structure_tie(s) = std::tuple<int, short>{10, 11};
0167 ///     assert(s.s == 11);
0168 /// \endcode
0169 template <class T>
0170 constexpr auto structure_tie(const T& val) noexcept {
0171     return detail::make_conststdtiedtuple_from_tietuple(
0172         detail::tie_as_tuple(const_cast<T&>(val)),
0173         detail::make_index_sequence< tuple_size_v<T> >()
0174     );
0175 }
0176 
0177 
0178 /// \overload structure_tie
0179 template <class T>
0180 constexpr auto structure_tie(T& val
0181 #if !BOOST_PFR_USE_CPP17
0182     , std::enable_if_t<std::is_assignable<T, T>::value>* = nullptr
0183 #endif
0184 ) noexcept {
0185     return detail::make_stdtiedtuple_from_tietuple(
0186         detail::tie_as_tuple(val),
0187         detail::make_index_sequence< tuple_size_v<T> >()
0188     );
0189 }
0190 
0191 #if !BOOST_PFR_USE_CPP17
0192 /// \overload structure_tie
0193 template <class T>
0194 constexpr auto structure_tie(T&, std::enable_if_t<!std::is_assignable<T, T>::value>* = nullptr) noexcept {
0195     static_assert(sizeof(T) && false, "====================> Boost.PFR: Calling boost::pfr::structure_tie on non const non assignable type is allowed only in C++17");
0196     return 0;
0197 }
0198 #endif
0199 
0200 
0201 /// \overload structure_tie
0202 template <class T>
0203 constexpr auto structure_tie(T&&, std::enable_if_t< std::is_rvalue_reference<T&&>::value>* = nullptr) noexcept {
0204     static_assert(sizeof(T) && false, "====================> Boost.PFR: Calling boost::pfr::structure_tie on rvalue references is forbidden");
0205     return 0;
0206 }
0207 
0208 /// Calls `func` for each field of a `value`.
0209 ///
0210 /// \param func must have one of the following signatures:
0211 ///     * any_return_type func(U&& field)                // field of value is perfect forwarded to function
0212 ///     * any_return_type func(U&& field, std::size_t i)
0213 ///     * any_return_type func(U&& value, I i)           // Here I is an `std::integral_constant<size_t, field_index>`
0214 ///
0215 /// \param value To each field of this variable will be the `func` applied.
0216 ///
0217 /// \b Example:
0218 /// \code
0219 ///     struct my_struct { int i, short s; };
0220 ///     int sum = 0;
0221 ///     boost::pfr::for_each_field(my_struct{20, 22}, [&sum](const auto& field) { sum += field; });
0222 ///     assert(sum == 42);
0223 /// \endcode
0224 template <class T, class F>
0225 constexpr void for_each_field(T&& value, F&& func) {
0226     return ::boost::pfr::detail::for_each_field(std::forward<T>(value), std::forward<F>(func));
0227 }
0228 
0229 /// \brief std::tie-like function that allows assigning to tied values from aggregates.
0230 ///
0231 /// \returns an object with lvalue references to `args...`; on assignment of an \aggregate value to that
0232 /// object each field of an aggregate is assigned to the corresponding `args...` reference.
0233 ///
0234 /// \b Example:
0235 /// \code
0236 ///     auto f() {
0237 ///       struct { struct { int x, y } p; short s; } res { { 4, 5 }, 6 };
0238 ///       return res;
0239 ///     }
0240 ///     auto [p, s] = f();
0241 ///     boost::pfr::tie_from_structure(p, s) = f();
0242 /// \endcode
0243 template <typename... Elements>
0244 constexpr detail::tie_from_structure_tuple<Elements...> tie_from_structure(Elements&... args) noexcept {
0245     return detail::tie_from_structure_tuple<Elements...>(args...);
0246 }
0247 
0248 BOOST_PFR_END_MODULE_EXPORT
0249 
0250 }} // namespace boost::pfr
0251 
0252 #endif // BOOST_PFR_CORE_HPP