sequence_tuple.hpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. // Copyright (c) 2016-2021 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. #include <utility> // metaprogramming stuff
  11. #include <cstddef> // std::size_t
  12. ///////////////////// Tuple that holds its values in the supplied order
  13. namespace boost { 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. return t.value;
  41. }
  42. template <std::size_t N, class T>
  43. constexpr const T& get_impl(const base_from_member<N, T>& t) noexcept {
  44. return t.value;
  45. }
  46. template <std::size_t N, class T>
  47. constexpr volatile T& get_impl(volatile base_from_member<N, T>& t) noexcept {
  48. return t.value;
  49. }
  50. template <std::size_t N, class T>
  51. constexpr const volatile T& get_impl(const volatile base_from_member<N, T>& t) noexcept {
  52. return t.value;
  53. }
  54. template <std::size_t N, class T>
  55. constexpr T&& get_impl(base_from_member<N, T>&& t) noexcept {
  56. return std::forward<T>(t.value);
  57. }
  58. template <class ...Values>
  59. struct tuple: tuple_base<
  60. detail::index_sequence_for<Values...>,
  61. Values...>
  62. {
  63. using tuple_base<
  64. detail::index_sequence_for<Values...>,
  65. Values...
  66. >::tuple_base;
  67. };
  68. template <std::size_t N, class ...T>
  69. constexpr decltype(auto) get(tuple<T...>& t) noexcept {
  70. static_assert(N < tuple<T...>::size_v, "====================> Boost.PFR: Tuple index out of bounds");
  71. return sequence_tuple::get_impl<N>(t);
  72. }
  73. template <std::size_t N, class ...T>
  74. constexpr decltype(auto) get(const tuple<T...>& t) noexcept {
  75. static_assert(N < tuple<T...>::size_v, "====================> Boost.PFR: Tuple index out of bounds");
  76. return sequence_tuple::get_impl<N>(t);
  77. }
  78. template <std::size_t N, class ...T>
  79. constexpr decltype(auto) get(const volatile tuple<T...>& t) noexcept {
  80. static_assert(N < tuple<T...>::size_v, "====================> Boost.PFR: Tuple index out of bounds");
  81. return sequence_tuple::get_impl<N>(t);
  82. }
  83. template <std::size_t N, class ...T>
  84. constexpr decltype(auto) get(volatile tuple<T...>& t) noexcept {
  85. static_assert(N < tuple<T...>::size_v, "====================> Boost.PFR: Tuple index out of bounds");
  86. return sequence_tuple::get_impl<N>(t);
  87. }
  88. template <std::size_t N, class ...T>
  89. constexpr decltype(auto) get(tuple<T...>&& t) noexcept {
  90. static_assert(N < tuple<T...>::size_v, "====================> Boost.PFR: Tuple index out of bounds");
  91. return sequence_tuple::get_impl<N>(std::move(t));
  92. }
  93. template <std::size_t I, class T>
  94. using tuple_element = std::remove_reference< decltype(
  95. ::boost::pfr::detail::sequence_tuple::get<I>( std::declval<T>() )
  96. ) >;
  97. }}}} // namespace boost::pfr::detail::sequence_tuple
  98. #endif // BOOST_PFR_CORE_HPP