123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141 |
- #ifndef BOOST_PFR_DETAIL_OFFSET_BASED_GETTER_HPP
- #define BOOST_PFR_DETAIL_OFFSET_BASED_GETTER_HPP
- #pragma once
- #include <boost/pfr/detail/config.hpp>
- #include <type_traits>
- #include <utility>
- #include <memory> // std::addressof
- #include <boost/pfr/detail/sequence_tuple.hpp>
- #include <boost/pfr/detail/rvalue_t.hpp>
- #include <boost/pfr/detail/size_t_.hpp>
- namespace boost { namespace pfr { namespace detail {
- template<std::size_t s, std::size_t a>
- struct internal_aligned_storage {
- alignas(a) char storage_[s];
- };
- template <typename T>
- struct tuple_of_aligned_storage;
- template <typename... Ts>
- struct tuple_of_aligned_storage<sequence_tuple::tuple<Ts...>> {
- using type = sequence_tuple::tuple<internal_aligned_storage<sizeof(Ts),
- #if defined(__GNUC__) && __GNUC__ < 8 && !defined(__x86_64__) && !defined(__CYGWIN__)
-
-
- (alignof(Ts) > 4 ? 4 : alignof(Ts))
- #else
- alignof(Ts)
- #endif
- >...>;
- };
- template <typename T>
- using tuple_of_aligned_storage_t = typename tuple_of_aligned_storage<T>::type;
- template <typename U, typename S>
- class offset_based_getter {
- using this_t = offset_based_getter<U, S>;
- 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?");
- static_assert(alignof(U) == alignof(S), "====================> Boost.PFR: Member sequence does not indicate correct alignment for struct type!");
- 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");
- 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");
- 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");
-
- template <std::size_t idx>
- using index_t = typename sequence_tuple::tuple_element<idx, S>::type;
-
-
-
- template <std::size_t idx>
- static constexpr std::ptrdiff_t offset() noexcept {
- constexpr tuple_of_aligned_storage_t<S> layout{};
- return &sequence_tuple::get<idx>(layout).storage_[0] - &sequence_tuple::get<0>(layout).storage_[0];
- }
-
- template <std::size_t idx>
- static index_t<idx> * get_pointer(U * u) noexcept {
- return reinterpret_cast<index_t<idx> *>(reinterpret_cast<char *>(u) + this_t::offset<idx>());
- }
- template <std::size_t idx>
- static const index_t<idx> * get_pointer(const U * u) noexcept {
- return reinterpret_cast<const index_t<idx> *>(reinterpret_cast<const char *>(u) + this_t::offset<idx>());
- }
- template <std::size_t idx>
- static volatile index_t<idx> * get_pointer(volatile U * u) noexcept {
- return reinterpret_cast<volatile index_t<idx> *>(reinterpret_cast<volatile char *>(u) + this_t::offset<idx>());
- }
- template <std::size_t idx>
- static const volatile index_t<idx> * get_pointer(const volatile U * u) noexcept {
- return reinterpret_cast<const volatile index_t<idx> *>(reinterpret_cast<const volatile char *>(u) + this_t::offset<idx>());
- }
- public:
- template <std::size_t idx>
- index_t<idx> & get(U & u, size_t_<idx>) const noexcept {
- return *this_t::get_pointer<idx>(std::addressof(u));
- }
- template <std::size_t idx>
- index_t<idx> const & get(U const & u, size_t_<idx>) const noexcept {
- return *this_t::get_pointer<idx>(std::addressof(u));
- }
- template <std::size_t idx>
- index_t<idx> volatile & get(U volatile & u, size_t_<idx>) const noexcept {
- return *this_t::get_pointer<idx>(std::addressof(u));
- }
- template <std::size_t idx>
- index_t<idx> const volatile & get(U const volatile & u, size_t_<idx>) const noexcept {
- return *this_t::get_pointer<idx>(std::addressof(u));
- }
-
- template <std::size_t idx>
- index_t<idx> && get(rvalue_t<U> u, size_t_<idx>) const = delete;
- };
- }}}
- #endif
|