// Copyright (c) 2016-2024 Antony Polukhin // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_PFR_DETAIL_MAKE_FLAT_TUPLE_OF_REFERENCES_HPP #define BOOST_PFR_DETAIL_MAKE_FLAT_TUPLE_OF_REFERENCES_HPP #pragma once #include #include // metaprogramming stuff #include #include #include namespace boost { namespace pfr { namespace detail { template using size_t_ = std::integral_constant; // Helper: Make a "getter" object corresponding to built-in tuple::get // For user-defined structures, the getter should be "offset_based_getter" struct sequence_tuple_getter { template decltype(auto) get(TupleOfReferences&& t, size_t_) const noexcept { return sequence_tuple::get(std::forward(t)); } }; template constexpr auto make_flat_tuple_of_references(TupleOrUserType&, const Getter&, size_t_, size_t_) noexcept; template constexpr sequence_tuple::tuple<> make_flat_tuple_of_references(TupleOrUserType&, const Getter&, size_t_, size_t_<0>) noexcept; template constexpr auto make_flat_tuple_of_references(TupleOrUserType&, const Getter&, size_t_, size_t_<1>) noexcept; template constexpr auto tie_as_tuple_with_references(T&... args) noexcept { return sequence_tuple::tuple{ args... }; } template constexpr decltype(auto) tie_as_tuple_with_references(detail::sequence_tuple::tuple& t) noexcept { return detail::make_flat_tuple_of_references(t, sequence_tuple_getter{}, size_t_<0>{}, size_t_::size_v>{}); } template constexpr decltype(auto) tie_as_tuple_with_references(const detail::sequence_tuple::tuple& t) noexcept { return detail::make_flat_tuple_of_references(t, sequence_tuple_getter{}, size_t_<0>{}, size_t_::size_v>{}); } template constexpr auto my_tuple_cat_impl(const Tuple1& t1, std::index_sequence, const Tuple2& t2, std::index_sequence) noexcept { return detail::tie_as_tuple_with_references( sequence_tuple::get(t1)..., sequence_tuple::get(t2)... ); } template constexpr auto my_tuple_cat(const Tuple1& t1, const Tuple2& t2) noexcept { return detail::my_tuple_cat_impl( t1, detail::make_index_sequence< Tuple1::size_v >{}, t2, detail::make_index_sequence< Tuple2::size_v >{} ); } template constexpr auto make_flat_tuple_of_references(TupleOrUserType& t, const Getter& g, size_t_, size_t_) noexcept { constexpr std::size_t next_size = Size / 2; return detail::my_tuple_cat( detail::make_flat_tuple_of_references(t, g, size_t_{}, size_t_{}), detail::make_flat_tuple_of_references(t, g, size_t_{}, size_t_{}) ); } template constexpr sequence_tuple::tuple<> make_flat_tuple_of_references(TupleOrUserType&, const Getter&, size_t_, size_t_<0>) noexcept { return {}; } template constexpr auto make_flat_tuple_of_references(TupleOrUserType& t, const Getter& g, size_t_, size_t_<1>) noexcept { return detail::tie_as_tuple_with_references( g.get(t, size_t_{}) ); } }}} // namespace boost::pfr::detail #endif // BOOST_PFR_DETAIL_MAKE_FLAT_TUPLE_OF_REFERENCES_HPP