File indexing completed on 2025-09-17 08:40:38
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021 #ifndef BOOST_PFR_DETAIL_CORE14_LOOPHOLE_HPP
0022 #define BOOST_PFR_DETAIL_CORE14_LOOPHOLE_HPP
0023 #pragma once
0024
0025 #include <boost/pfr/detail/config.hpp>
0026
0027 #ifdef BOOST_PFR_HAS_STD_MODULE
0028 import std;
0029 #else
0030 #include <type_traits>
0031 #include <utility>
0032 #endif
0033
0034 #include <boost/pfr/detail/offset_based_getter.hpp>
0035 #include <boost/pfr/detail/fields_count.hpp>
0036 #include <boost/pfr/detail/make_flat_tuple_of_references.hpp>
0037 #include <boost/pfr/detail/make_integer_sequence.hpp>
0038 #include <boost/pfr/detail/sequence_tuple.hpp>
0039 #include <boost/pfr/detail/rvalue_t.hpp>
0040 #include <boost/pfr/detail/unsafe_declval.hpp>
0041
0042
0043 #ifdef __clang__
0044 # pragma clang diagnostic push
0045 # pragma clang diagnostic ignored "-Wmissing-braces"
0046 # pragma clang diagnostic ignored "-Wundefined-inline"
0047 # pragma clang diagnostic ignored "-Wundefined-internal"
0048 # pragma clang diagnostic ignored "-Wmissing-field-initializers"
0049 #elif defined(__GNUC__)
0050 # pragma GCC diagnostic push
0051 # pragma GCC diagnostic ignored "-Wnon-template-friend"
0052 #endif
0053
0054
0055 namespace boost { namespace pfr { namespace detail {
0056
0057
0058
0059
0060
0061
0062 template <class T, std::size_t N>
0063 struct tag {
0064 friend auto loophole(tag<T,N>);
0065 };
0066
0067
0068 template <class T, class U, std::size_t N, bool B>
0069 struct fn_def_lref {
0070 friend auto loophole(tag<T,N>) {
0071
0072
0073
0074
0075 using no_extents_t = std::remove_all_extents_t<U>;
0076 return static_cast< std::conditional_t<std::is_move_constructible<no_extents_t>::value, no_extents_t&&, no_extents_t&> >(
0077 boost::pfr::detail::unsafe_declval<no_extents_t&>()
0078 );
0079 }
0080 };
0081 template <class T, class U, std::size_t N, bool B>
0082 struct fn_def_rref {
0083 friend auto loophole(tag<T,N>) { return std::move(boost::pfr::detail::unsafe_declval< std::remove_all_extents_t<U>& >()); }
0084 };
0085
0086
0087
0088 template <class T, class U, std::size_t N>
0089 struct fn_def_lref<T, U, N, true> {};
0090
0091 template <class T, class U, std::size_t N>
0092 struct fn_def_rref<T, U, N, true> {};
0093
0094
0095
0096
0097
0098
0099 template <class T, std::size_t N>
0100 struct loophole_ubiq_lref {
0101 template<class U, std::size_t M> static std::size_t ins(...);
0102 template<class U, std::size_t M, std::size_t = sizeof(loophole(tag<T,M>{})) > static char ins(int);
0103
0104 template<class U, std::size_t = sizeof(fn_def_lref<T, U, N, sizeof(ins<U, N>(0)) == sizeof(char)>)>
0105 constexpr operator U&() const&& noexcept;
0106 };
0107
0108 template <class T, std::size_t N>
0109 struct loophole_ubiq_rref {
0110 template<class U, std::size_t M> static std::size_t ins(...);
0111 template<class U, std::size_t M, std::size_t = sizeof(loophole(tag<T,M>{})) > static char ins(int);
0112
0113 template<class U, std::size_t = sizeof(fn_def_rref<T, U, N, sizeof(ins<U, N>(0)) == sizeof(char)>)>
0114 constexpr operator U&&() const&& noexcept;
0115 };
0116
0117
0118
0119 template <class T, class U>
0120 struct loophole_type_list_lref;
0121
0122 template <typename T, std::size_t... I>
0123 struct loophole_type_list_lref< T, std::index_sequence<I...> >
0124
0125 : sequence_tuple::tuple< decltype(T{ loophole_ubiq_lref<T, I>{}... }, 0) >
0126 {
0127 using type = sequence_tuple::tuple< decltype(loophole(tag<T, I>{}))... >;
0128 };
0129
0130
0131 template <class T, class U>
0132 struct loophole_type_list_rref;
0133
0134 template <typename T, std::size_t... I>
0135 struct loophole_type_list_rref< T, std::index_sequence<I...> >
0136
0137 : sequence_tuple::tuple< decltype(T{ loophole_ubiq_rref<T, I>{}... }, 0) >
0138 {
0139 using type = sequence_tuple::tuple< decltype(loophole(tag<T, I>{}))... >;
0140 };
0141
0142
0143
0144 template <bool IsCopyConstructible , class T, class U>
0145 struct loophole_type_list_selector {
0146 using type = loophole_type_list_lref<T, U>;
0147 };
0148
0149 template <class T, class U>
0150 struct loophole_type_list_selector<false , T, U> {
0151 using type = loophole_type_list_rref<T, U>;
0152 };
0153
0154 template <class T>
0155 auto tie_as_tuple_loophole_impl(T& lvalue) noexcept {
0156 using type = std::remove_cv_t<std::remove_reference_t<T>>;
0157 using indexes = detail::make_index_sequence<fields_count<type>()>;
0158 using loophole_type_list = typename detail::loophole_type_list_selector<
0159 std::is_copy_constructible<std::remove_all_extents_t<type>>::value, type, indexes
0160 >::type;
0161 using tuple_type = typename loophole_type_list::type;
0162
0163 return boost::pfr::detail::make_flat_tuple_of_references(
0164 lvalue,
0165 offset_based_getter<type, tuple_type>{},
0166 size_t_<0>{},
0167 size_t_<tuple_type::size_v>{}
0168 );
0169 }
0170
0171 template <class T>
0172 auto tie_as_tuple(T& val) noexcept {
0173 static_assert(
0174 !std::is_union<T>::value,
0175 "====================> Boost.PFR: For safety reasons it is forbidden to reflect unions. See `Reflection of unions` section in the docs for more info."
0176 );
0177 return boost::pfr::detail::tie_as_tuple_loophole_impl(
0178 val
0179 );
0180 }
0181
0182 template <class T, class F, std::size_t... I>
0183 void for_each_field_dispatcher(T& t, F&& f, std::index_sequence<I...>) {
0184 static_assert(
0185 !std::is_union<T>::value,
0186 "====================> Boost.PFR: For safety reasons it is forbidden to reflect unions. See `Reflection of unions` section in the docs for more info."
0187 );
0188 std::forward<F>(f)(
0189 boost::pfr::detail::tie_as_tuple_loophole_impl(t)
0190 );
0191 }
0192
0193 }}}
0194
0195
0196 #ifdef __clang__
0197 # pragma clang diagnostic pop
0198 #elif defined(__GNUC__)
0199 # pragma GCC diagnostic pop
0200 #endif
0201
0202
0203 #endif
0204