Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:43:38

0001 // Copyright (c) 2016-2023 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_impl.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 /// \brief Returns reference or const reference to a field with index `I` in \aggregate `val`.
0033 /// Overload taking the type `U` returns reference or const reference to a field
0034 /// with provided type `U` in \aggregate `val` if there's only one field of such type in `val`.
0035 ///
0036 /// \b Example:
0037 /// \code
0038 ///     struct my_struct { int i, short s; };
0039 ///     my_struct s {10, 11};
0040 ///
0041 ///     assert(boost::pfr::get<0>(s) == 10);
0042 ///     boost::pfr::get<1>(s) = 0;
0043 ///
0044 ///     assert(boost::pfr::get<int>(s) == 10);
0045 ///     boost::pfr::get<short>(s) = 11;
0046 /// \endcode
0047 template <std::size_t I, class T>
0048 constexpr decltype(auto) get(const T& val) noexcept {
0049     return detail::sequence_tuple::get<I>( detail::tie_as_tuple(val) );
0050 }
0051 
0052 /// \overload get
0053 template <std::size_t I, class T>
0054 constexpr decltype(auto) get(T& val
0055 #if !BOOST_PFR_USE_CPP17
0056     , std::enable_if_t<std::is_assignable<T, T>::value>* = nullptr
0057 #endif
0058 ) noexcept {
0059     return detail::sequence_tuple::get<I>( detail::tie_as_tuple(val) );
0060 }
0061 
0062 #if !BOOST_PFR_USE_CPP17
0063 /// \overload get
0064 template <std::size_t I, class T>
0065 constexpr auto get(T&, std::enable_if_t<!std::is_assignable<T, T>::value>* = nullptr) noexcept {
0066     static_assert(sizeof(T) && false, "====================> Boost.PFR: Calling boost::pfr::get on non const non assignable type is allowed only in C++17");
0067     return 0;
0068 }
0069 #endif
0070 
0071 
0072 /// \overload get
0073 template <std::size_t I, class T>
0074 constexpr auto get(T&& val, std::enable_if_t< std::is_rvalue_reference<T&&>::value>* = nullptr) noexcept {
0075     return std::move(detail::sequence_tuple::get<I>( detail::tie_as_tuple(val) ));
0076 }
0077 
0078 
0079 /// \overload get
0080 template <class U, class T>
0081 constexpr const U& get(const T& val) noexcept {
0082     return detail::sequence_tuple::get_by_type_impl<const U&>( detail::tie_as_tuple(val) );
0083 }
0084 
0085 
0086 /// \overload get
0087 template <class U, class T>
0088 constexpr U& get(T& val
0089 #if !BOOST_PFR_USE_CPP17
0090     , std::enable_if_t<std::is_assignable<T, T>::value>* = nullptr
0091 #endif
0092 ) noexcept {
0093     return detail::sequence_tuple::get_by_type_impl<U&>( detail::tie_as_tuple(val) );
0094 }
0095 
0096 #if !BOOST_PFR_USE_CPP17
0097 /// \overload get
0098 template <class U, class T>
0099 constexpr U& get(T&, std::enable_if_t<!std::is_assignable<T, T>::value>* = nullptr) noexcept {
0100     static_assert(sizeof(T) && false, "====================> Boost.PFR: Calling boost::pfr::get on non const non assignable type is allowed only in C++17");
0101     return 0;
0102 }
0103 #endif
0104 
0105 
0106 /// \overload get
0107 template <class U, class T>
0108 constexpr U&& get(T&& val, std::enable_if_t< std::is_rvalue_reference<T&&>::value>* = nullptr) noexcept {
0109     return std::move(detail::sequence_tuple::get_by_type_impl<U&>( detail::tie_as_tuple(val) ));
0110 }
0111 
0112 
0113 /// \brief `tuple_element` has a member typedef `type` that returns the type of a field with index I in \aggregate T.
0114 ///
0115 /// \b Example:
0116 /// \code
0117 ///     std::vector< boost::pfr::tuple_element<0, my_structure>::type > v;
0118 /// \endcode
0119 template <std::size_t I, class T>
0120 using tuple_element = detail::sequence_tuple::tuple_element<I, decltype( ::boost::pfr::detail::tie_as_tuple(std::declval<T&>()) ) >;
0121 
0122 
0123 /// \brief Type of a field with index `I` in \aggregate `T`.
0124 ///
0125 /// \b Example:
0126 /// \code
0127 ///     std::vector< boost::pfr::tuple_element_t<0, my_structure> > v;
0128 /// \endcode
0129 template <std::size_t I, class T>
0130 using tuple_element_t = typename tuple_element<I, T>::type;
0131 
0132 
0133 /// \brief Creates a `std::tuple` from fields of an \aggregate `val`.
0134 ///
0135 /// \b Example:
0136 /// \code
0137 ///     struct my_struct { int i, short s; };
0138 ///     my_struct s {10, 11};
0139 ///     std::tuple<int, short> t = boost::pfr::structure_to_tuple(s);
0140 ///     assert(get<0>(t) == 10);
0141 /// \endcode
0142 template <class T>
0143 constexpr auto structure_to_tuple(const T& val) noexcept {
0144     return detail::make_stdtuple_from_tietuple(
0145         detail::tie_as_tuple(val),
0146         detail::make_index_sequence< tuple_size_v<T> >()
0147     );
0148 }
0149 
0150 
0151 /// \brief std::tie` like function that ties fields of a structure.
0152 ///
0153 /// \returns a `std::tuple` with lvalue and const lvalue references to fields of an \aggregate `val`.
0154 ///
0155 /// \b Example:
0156 /// \code
0157 ///     void foo(const int&, const short&);
0158 ///     struct my_struct { int i, short s; };
0159 ///
0160 ///     const my_struct const_s{1, 2};
0161 ///     std::apply(foo, boost::pfr::structure_tie(const_s));
0162 ///
0163 ///     my_struct s;
0164 ///     boost::pfr::structure_tie(s) = std::tuple<int, short>{10, 11};
0165 ///     assert(s.s == 11);
0166 /// \endcode
0167 template <class T>
0168 constexpr auto structure_tie(const T& val) noexcept {
0169     return detail::make_conststdtiedtuple_from_tietuple(
0170         detail::tie_as_tuple(const_cast<T&>(val)),
0171         detail::make_index_sequence< tuple_size_v<T> >()
0172     );
0173 }
0174 
0175 
0176 /// \overload structure_tie
0177 template <class T>
0178 constexpr auto structure_tie(T& val
0179 #if !BOOST_PFR_USE_CPP17
0180     , std::enable_if_t<std::is_assignable<T, T>::value>* = nullptr
0181 #endif
0182 ) noexcept {
0183     return detail::make_stdtiedtuple_from_tietuple(
0184         detail::tie_as_tuple(val),
0185         detail::make_index_sequence< tuple_size_v<T> >()
0186     );
0187 }
0188 
0189 #if !BOOST_PFR_USE_CPP17
0190 /// \overload structure_tie
0191 template <class T>
0192 constexpr auto structure_tie(T&, std::enable_if_t<!std::is_assignable<T, T>::value>* = nullptr) noexcept {
0193     static_assert(sizeof(T) && false, "====================> Boost.PFR: Calling boost::pfr::structure_tie on non const non assignable type is allowed only in C++17");
0194     return 0;
0195 }
0196 #endif
0197 
0198 
0199 /// \overload structure_tie
0200 template <class T>
0201 constexpr auto structure_tie(T&&, std::enable_if_t< std::is_rvalue_reference<T&&>::value>* = nullptr) noexcept {
0202     static_assert(sizeof(T) && false, "====================> Boost.PFR: Calling boost::pfr::structure_tie on rvalue references is forbidden");
0203     return 0;
0204 }
0205 
0206 /// Calls `func` for each field of a `value`.
0207 ///
0208 /// \param func must have one of the following signatures:
0209 ///     * any_return_type func(U&& field)                // field of value is perfect forwarded to function
0210 ///     * any_return_type func(U&& field, std::size_t i)
0211 ///     * any_return_type func(U&& value, I i)           // Here I is an `std::integral_constant<size_t, field_index>`
0212 ///
0213 /// \param value To each field of this variable will be the `func` applied.
0214 ///
0215 /// \b Example:
0216 /// \code
0217 ///     struct my_struct { int i, short s; };
0218 ///     int sum = 0;
0219 ///     boost::pfr::for_each_field(my_struct{20, 22}, [&sum](const auto& field) { sum += field; });
0220 ///     assert(sum == 42);
0221 /// \endcode
0222 template <class T, class F>
0223 constexpr void for_each_field(T&& value, F&& func) {
0224     constexpr std::size_t fields_count_val = boost::pfr::detail::fields_count<std::remove_reference_t<T>>();
0225 
0226     ::boost::pfr::detail::for_each_field_dispatcher(
0227         value,
0228         [f = std::forward<F>(func)](auto&& t) mutable {
0229             // MSVC related workaround. Its lambdas do not capture constexprs.
0230             constexpr std::size_t fields_count_val_in_lambda
0231                 = boost::pfr::detail::fields_count<std::remove_reference_t<T>>();
0232 
0233             ::boost::pfr::detail::for_each_field_impl(
0234                 t,
0235                 std::forward<F>(f),
0236                 detail::make_index_sequence<fields_count_val_in_lambda>{},
0237                 std::is_rvalue_reference<T&&>{}
0238             );
0239         },
0240         detail::make_index_sequence<fields_count_val>{}
0241     );
0242 }
0243 
0244 /// \brief std::tie-like function that allows assigning to tied values from aggregates.
0245 ///
0246 /// \returns an object with lvalue references to `args...`; on assignment of an \aggregate value to that
0247 /// object each field of an aggregate is assigned to the corresponding `args...` reference.
0248 ///
0249 /// \b Example:
0250 /// \code
0251 ///     auto f() {
0252 ///       struct { struct { int x, y } p; short s; } res { { 4, 5 }, 6 };
0253 ///       return res;
0254 ///     }
0255 ///     auto [p, s] = f();
0256 ///     boost::pfr::tie_from_structure(p, s) = f();
0257 /// \endcode
0258 template <typename... Elements>
0259 constexpr detail::tie_from_structure_tuple<Elements...> tie_from_structure(Elements&... args) noexcept {
0260     return detail::tie_from_structure_tuple<Elements...>(args...);
0261 }
0262 
0263 }} // namespace boost::pfr
0264 
0265 #endif // BOOST_PFR_CORE_HPP