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