make_flat_tuple_of_references.hpp 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. // Copyright (c) 2016-2023 Antony Polukhin
  2. //
  3. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  4. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. #ifndef BHO_PFR_DETAIL_MAKE_FLAT_TUPLE_OF_REFERENCES_HPP
  6. #define BHO_PFR_DETAIL_MAKE_FLAT_TUPLE_OF_REFERENCES_HPP
  7. #pragma once
  8. #include <asio2/bho/pfr/detail/config.hpp>
  9. #include <utility> // metaprogramming stuff
  10. #include <asio2/bho/pfr/detail/sequence_tuple.hpp>
  11. #include <asio2/bho/pfr/detail/rvalue_t.hpp>
  12. #include <asio2/bho/pfr/detail/make_integer_sequence.hpp>
  13. namespace bho { namespace pfr { namespace detail {
  14. template <std::size_t Index>
  15. using size_t_ = std::integral_constant<std::size_t, Index >;
  16. // Helper: Make a "getter" object corresponding to built-in tuple::get
  17. // For user-defined structures, the getter should be "offset_based_getter"
  18. struct sequence_tuple_getter {
  19. template <std::size_t idx, typename TupleOfReferences>
  20. decltype(auto) get(TupleOfReferences&& t, size_t_<idx>) const noexcept {
  21. return sequence_tuple::get<idx>(std::forward<TupleOfReferences>(t));
  22. }
  23. };
  24. template <class TupleOrUserType, class Getter, std::size_t Begin, std::size_t Size>
  25. constexpr auto make_flat_tuple_of_references(TupleOrUserType&, const Getter&, size_t_<Begin>, size_t_<Size>) noexcept;
  26. template <class TupleOrUserType, class Getter, std::size_t Begin>
  27. constexpr sequence_tuple::tuple<> make_flat_tuple_of_references(TupleOrUserType&, const Getter&, size_t_<Begin>, size_t_<0>) noexcept;
  28. template <class TupleOrUserType, class Getter, std::size_t Begin>
  29. constexpr auto make_flat_tuple_of_references(TupleOrUserType&, const Getter&, size_t_<Begin>, size_t_<1>) noexcept;
  30. template <class... T>
  31. constexpr auto tie_as_tuple_with_references(T&... args) noexcept {
  32. return sequence_tuple::tuple<T&...>{ args... };
  33. }
  34. template <class... T>
  35. constexpr decltype(auto) tie_as_tuple_with_references(detail::sequence_tuple::tuple<T...>& t) noexcept {
  36. return detail::make_flat_tuple_of_references(t, sequence_tuple_getter{}, size_t_<0>{}, size_t_<sequence_tuple::tuple<T...>::size_v>{});
  37. }
  38. template <class... T>
  39. constexpr decltype(auto) tie_as_tuple_with_references(const detail::sequence_tuple::tuple<T...>& t) noexcept {
  40. return detail::make_flat_tuple_of_references(t, sequence_tuple_getter{}, size_t_<0>{}, size_t_<sequence_tuple::tuple<T...>::size_v>{});
  41. }
  42. template <class Tuple1, std::size_t... I1, class Tuple2, std::size_t... I2>
  43. constexpr auto my_tuple_cat_impl(const Tuple1& t1, std::index_sequence<I1...>, const Tuple2& t2, std::index_sequence<I2...>) noexcept {
  44. return detail::tie_as_tuple_with_references(
  45. sequence_tuple::get<I1>(t1)...,
  46. sequence_tuple::get<I2>(t2)...
  47. );
  48. }
  49. template <class Tuple1, class Tuple2>
  50. constexpr auto my_tuple_cat(const Tuple1& t1, const Tuple2& t2) noexcept {
  51. return detail::my_tuple_cat_impl(
  52. t1, detail::make_index_sequence< Tuple1::size_v >{},
  53. t2, detail::make_index_sequence< Tuple2::size_v >{}
  54. );
  55. }
  56. template <class TupleOrUserType, class Getter, std::size_t Begin, std::size_t Size>
  57. constexpr auto make_flat_tuple_of_references(TupleOrUserType& t, const Getter& g, size_t_<Begin>, size_t_<Size>) noexcept {
  58. constexpr std::size_t next_size = Size / 2;
  59. return detail::my_tuple_cat(
  60. detail::make_flat_tuple_of_references(t, g, size_t_<Begin>{}, size_t_<next_size>{}),
  61. detail::make_flat_tuple_of_references(t, g, size_t_<Begin + Size / 2>{}, size_t_<Size - next_size>{})
  62. );
  63. }
  64. template <class TupleOrUserType, class Getter, std::size_t Begin>
  65. constexpr sequence_tuple::tuple<> make_flat_tuple_of_references(TupleOrUserType&, const Getter&, size_t_<Begin>, size_t_<0>) noexcept {
  66. return {};
  67. }
  68. template <class TupleOrUserType, class Getter, std::size_t Begin>
  69. constexpr auto make_flat_tuple_of_references(TupleOrUserType& t, const Getter& g, size_t_<Begin>, size_t_<1>) noexcept {
  70. return detail::tie_as_tuple_with_references(
  71. g.get(t, size_t_<Begin>{})
  72. );
  73. }
  74. }}} // namespace bho::pfr::detail
  75. #endif // BHO_PFR_DETAIL_MAKE_FLAT_TUPLE_OF_REFERENCES_HPP