File indexing completed on 2025-09-17 08:41:00
0001
0002
0003
0004
0005
0006
0007 #ifndef BOOST_PFR_DETAIL_OFFSET_BASED_GETTER_HPP
0008 #define BOOST_PFR_DETAIL_OFFSET_BASED_GETTER_HPP
0009 #pragma once
0010
0011 #include <boost/pfr/detail/config.hpp>
0012
0013 #ifdef BOOST_PFR_HAS_STD_MODULE
0014 import std;
0015 #else
0016 #include <type_traits>
0017 #include <utility>
0018 #include <memory> // std::addressof
0019 #endif
0020
0021 #include <boost/pfr/detail/sequence_tuple.hpp>
0022 #include <boost/pfr/detail/rvalue_t.hpp>
0023 #include <boost/pfr/detail/size_t_.hpp>
0024
0025
0026 namespace boost { namespace pfr { namespace detail {
0027
0028
0029
0030
0031 template<std::size_t s, std::size_t a>
0032 struct internal_aligned_storage {
0033 alignas(a) char storage_[s];
0034 };
0035
0036
0037
0038
0039
0040
0041
0042 template <typename T>
0043 struct tuple_of_aligned_storage;
0044
0045 template <typename... Ts>
0046 struct tuple_of_aligned_storage<sequence_tuple::tuple<Ts...>> {
0047 using type = sequence_tuple::tuple<internal_aligned_storage<sizeof(Ts),
0048 #if defined(__GNUC__) && __GNUC__ < 8 && !defined(__x86_64__) && !defined(__CYGWIN__)
0049
0050
0051 (alignof(Ts) > 4 ? 4 : alignof(Ts))
0052 #else
0053 alignof(Ts)
0054 #endif
0055 >...>;
0056 };
0057
0058
0059
0060 template <typename T>
0061 using tuple_of_aligned_storage_t = typename tuple_of_aligned_storage<T>::type;
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072 template <typename U, typename S>
0073 class offset_based_getter {
0074 using this_t = offset_based_getter<U, S>;
0075
0076 static_assert(sizeof(U) == sizeof(S), "====================> Boost.PFR: Member sequence does not indicate correct size for struct type! Maybe the user-provided type is not a SimpleAggregate?");
0077 static_assert(alignof(U) == alignof(S), "====================> Boost.PFR: Member sequence does not indicate correct alignment for struct type!");
0078
0079 static_assert(!std::is_const<U>::value, "====================> Boost.PFR: const should be stripped from user-defined type when using offset_based_getter or overload resolution will be ambiguous later, this indicates an error within pfr");
0080 static_assert(!std::is_reference<U>::value, "====================> Boost.PFR: reference should be stripped from user-defined type when using offset_based_getter or overload resolution will be ambiguous later, this indicates an error within pfr");
0081 static_assert(!std::is_volatile<U>::value, "====================> Boost.PFR: volatile should be stripped from user-defined type when using offset_based_getter or overload resolution will be ambiguous later. this indicates an error within pfr");
0082
0083
0084 template <std::size_t idx>
0085 using index_t = typename sequence_tuple::tuple_element<idx, S>::type;
0086
0087
0088
0089
0090 template <std::size_t idx>
0091 static constexpr std::ptrdiff_t offset() noexcept {
0092 constexpr tuple_of_aligned_storage_t<S> layout{};
0093 return &sequence_tuple::get<idx>(layout).storage_[0] - &sequence_tuple::get<0>(layout).storage_[0];
0094 }
0095
0096
0097 template <std::size_t idx>
0098 static index_t<idx> * get_pointer(U * u) noexcept {
0099 return reinterpret_cast<index_t<idx> *>(reinterpret_cast<char *>(u) + this_t::offset<idx>());
0100 }
0101
0102 template <std::size_t idx>
0103 static const index_t<idx> * get_pointer(const U * u) noexcept {
0104 return reinterpret_cast<const index_t<idx> *>(reinterpret_cast<const char *>(u) + this_t::offset<idx>());
0105 }
0106
0107 template <std::size_t idx>
0108 static volatile index_t<idx> * get_pointer(volatile U * u) noexcept {
0109 return reinterpret_cast<volatile index_t<idx> *>(reinterpret_cast<volatile char *>(u) + this_t::offset<idx>());
0110 }
0111
0112 template <std::size_t idx>
0113 static const volatile index_t<idx> * get_pointer(const volatile U * u) noexcept {
0114 return reinterpret_cast<const volatile index_t<idx> *>(reinterpret_cast<const volatile char *>(u) + this_t::offset<idx>());
0115 }
0116
0117 public:
0118 template <std::size_t idx>
0119 index_t<idx> & get(U & u, size_t_<idx>) const noexcept {
0120 return *this_t::get_pointer<idx>(std::addressof(u));
0121 }
0122
0123 template <std::size_t idx>
0124 index_t<idx> const & get(U const & u, size_t_<idx>) const noexcept {
0125 return *this_t::get_pointer<idx>(std::addressof(u));
0126 }
0127
0128 template <std::size_t idx>
0129 index_t<idx> volatile & get(U volatile & u, size_t_<idx>) const noexcept {
0130 return *this_t::get_pointer<idx>(std::addressof(u));
0131 }
0132
0133 template <std::size_t idx>
0134 index_t<idx> const volatile & get(U const volatile & u, size_t_<idx>) const noexcept {
0135 return *this_t::get_pointer<idx>(std::addressof(u));
0136 }
0137
0138
0139 template <std::size_t idx>
0140 index_t<idx> && get(rvalue_t<U> u, size_t_<idx>) const = delete;
0141 };
0142
0143
0144 }}}
0145
0146 #endif