sequence_tuple.hpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  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_SEQUENCE_TUPLE_HPP
  6. #define BHO_PFR_DETAIL_SEQUENCE_TUPLE_HPP
  7. #pragma once
  8. #include <asio2/bho/pfr/detail/config.hpp>
  9. #include <asio2/bho/pfr/detail/make_integer_sequence.hpp>
  10. #include <utility> // metaprogramming stuff
  11. #include <cstddef> // std::size_t
  12. ///////////////////// Tuple that holds its values in the supplied order
  13. namespace bho { namespace pfr { namespace detail { namespace sequence_tuple {
  14. template <std::size_t N, class T>
  15. struct base_from_member {
  16. T value;
  17. };
  18. template <class I, class ...Tail>
  19. struct tuple_base;
  20. template <std::size_t... I, class ...Tail>
  21. struct tuple_base< std::index_sequence<I...>, Tail... >
  22. : base_from_member<I , Tail>...
  23. {
  24. static constexpr std::size_t size_v = sizeof...(I);
  25. // We do not use `noexcept` in the following functions, because if user forget to put one then clang will issue an error:
  26. // "error: exception specification of explicitly defaulted default constructor does not match the calculated one".
  27. constexpr tuple_base() = default;
  28. constexpr tuple_base(tuple_base&&) = default;
  29. constexpr tuple_base(const tuple_base&) = default;
  30. constexpr tuple_base(Tail... v) noexcept
  31. : base_from_member<I, Tail>{ v }...
  32. {}
  33. };
  34. template <>
  35. struct tuple_base<std::index_sequence<> > {
  36. static constexpr std::size_t size_v = 0;
  37. };
  38. template <std::size_t N, class T>
  39. constexpr T& get_impl(base_from_member<N, T>& t) noexcept {
  40. // NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn)
  41. return t.value;
  42. }
  43. template <std::size_t N, class T>
  44. constexpr const T& get_impl(const base_from_member<N, T>& t) noexcept {
  45. // NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn)
  46. return t.value;
  47. }
  48. template <std::size_t N, class T>
  49. constexpr volatile T& get_impl(volatile base_from_member<N, T>& t) noexcept {
  50. // NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn)
  51. return t.value;
  52. }
  53. template <std::size_t N, class T>
  54. constexpr const volatile T& get_impl(const volatile base_from_member<N, T>& t) noexcept {
  55. // NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn)
  56. return t.value;
  57. }
  58. template <std::size_t N, class T>
  59. constexpr T&& get_impl(base_from_member<N, T>&& t) noexcept {
  60. // NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn)
  61. return std::forward<T>(t.value);
  62. }
  63. template <class T, std::size_t N>
  64. constexpr T& get_by_type_impl(base_from_member<N, T>& t) noexcept {
  65. // NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn)
  66. return t.value;
  67. }
  68. template <class T, std::size_t N>
  69. constexpr const T& get_by_type_impl(const base_from_member<N, T>& t) noexcept {
  70. // NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn)
  71. return t.value;
  72. }
  73. template <class T, std::size_t N>
  74. constexpr volatile T& get_by_type_impl(volatile base_from_member<N, T>& t) noexcept {
  75. // NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn)
  76. return t.value;
  77. }
  78. template <class T, std::size_t N>
  79. constexpr const volatile T& get_by_type_impl(const volatile base_from_member<N, T>& t) noexcept {
  80. // NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn)
  81. return t.value;
  82. }
  83. template <class T, std::size_t N>
  84. constexpr T&& get_by_type_impl(base_from_member<N, T>&& t) noexcept {
  85. // NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn)
  86. return std::forward<T>(t.value);
  87. }
  88. template <class T, std::size_t N>
  89. constexpr const T&& get_by_type_impl(const base_from_member<N, T>&& t) noexcept {
  90. // NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn)
  91. return std::forward<T>(t.value);
  92. }
  93. template <class ...Values>
  94. struct tuple: tuple_base<
  95. detail::index_sequence_for<Values...>,
  96. Values...>
  97. {
  98. using tuple_base<
  99. detail::index_sequence_for<Values...>,
  100. Values...
  101. >::tuple_base;
  102. constexpr static std::size_t size() noexcept { return sizeof...(Values); }
  103. constexpr static bool empty() noexcept { return size() == 0; }
  104. };
  105. template <std::size_t N, class ...T>
  106. constexpr decltype(auto) get(tuple<T...>& t) noexcept {
  107. static_assert(N < tuple<T...>::size_v, "====================> BHO.PFR: Tuple index out of bounds");
  108. return sequence_tuple::get_impl<N>(t);
  109. }
  110. template <std::size_t N, class ...T>
  111. constexpr decltype(auto) get(const tuple<T...>& t) noexcept {
  112. static_assert(N < tuple<T...>::size_v, "====================> BHO.PFR: Tuple index out of bounds");
  113. return sequence_tuple::get_impl<N>(t);
  114. }
  115. template <std::size_t N, class ...T>
  116. constexpr decltype(auto) get(const volatile tuple<T...>& t) noexcept {
  117. static_assert(N < tuple<T...>::size_v, "====================> BHO.PFR: Tuple index out of bounds");
  118. return sequence_tuple::get_impl<N>(t);
  119. }
  120. template <std::size_t N, class ...T>
  121. constexpr decltype(auto) get(volatile tuple<T...>& t) noexcept {
  122. static_assert(N < tuple<T...>::size_v, "====================> BHO.PFR: Tuple index out of bounds");
  123. return sequence_tuple::get_impl<N>(t);
  124. }
  125. template <std::size_t N, class ...T>
  126. constexpr decltype(auto) get(tuple<T...>&& t) noexcept {
  127. static_assert(N < tuple<T...>::size_v, "====================> BHO.PFR: Tuple index out of bounds");
  128. return sequence_tuple::get_impl<N>(std::move(t));
  129. }
  130. template <std::size_t I, class T>
  131. using tuple_element = std::remove_reference< decltype(
  132. ::bho::pfr::detail::sequence_tuple::get<I>( std::declval<T>() )
  133. ) >;
  134. template <class... Args>
  135. constexpr auto make_sequence_tuple(Args... args) noexcept {
  136. return ::bho::pfr::detail::sequence_tuple::tuple<Args...>{ args... };
  137. }
  138. }}}} // namespace bho::pfr::detail::sequence_tuple
  139. #endif // BHO_PFR_CORE_HPP