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