sequence_tuple.hpp 6.2 KB

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