1 // Copyright (c) 2016-2022 Antony Polukhin
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)
6 #ifndef BOOST_PFR_DETAIL_SEQUENCE_TUPLE_HPP
7 #define BOOST_PFR_DETAIL_SEQUENCE_TUPLE_HPP
10 #include <boost/pfr/detail/config.hpp>
11 #include <boost/pfr/detail/make_integer_sequence.hpp>
13 #include <utility> // metaprogramming stuff
14 #include <cstddef> // std::size_t
16 ///////////////////// Tuple that holds its values in the supplied order
17 namespace boost { namespace pfr { namespace detail { namespace sequence_tuple {
19 template <std::size_t N, class T>
20 struct base_from_member {
24 template <class I, class ...Tail>
29 template <std::size_t... I, class ...Tail>
30 struct tuple_base< std::index_sequence<I...>, Tail... >
31 : base_from_member<I , Tail>...
33 static constexpr std::size_t size_v = sizeof...(I);
35 // We do not use `noexcept` in the following functions, because if user forget to put one then clang will issue an error:
36 // "error: exception specification of explicitly defaulted default constructor does not match the calculated one".
37 constexpr tuple_base() = default;
38 constexpr tuple_base(tuple_base&&) = default;
39 constexpr tuple_base(const tuple_base&) = default;
41 constexpr tuple_base(Tail... v) noexcept
42 : base_from_member<I, Tail>{ v }...
47 struct tuple_base<std::index_sequence<> > {
48 static constexpr std::size_t size_v = 0;
51 template <std::size_t N, class T>
52 constexpr T& get_impl(base_from_member<N, T>& t) noexcept {
56 template <std::size_t N, class T>
57 constexpr const T& get_impl(const base_from_member<N, T>& t) noexcept {
61 template <std::size_t N, class T>
62 constexpr volatile T& get_impl(volatile base_from_member<N, T>& t) noexcept {
66 template <std::size_t N, class T>
67 constexpr const volatile T& get_impl(const volatile base_from_member<N, T>& t) noexcept {
71 template <std::size_t N, class T>
72 constexpr T&& get_impl(base_from_member<N, T>&& t) noexcept {
73 return std::forward<T>(t.value);
77 template <class ...Values>
78 struct tuple: tuple_base<
79 detail::index_sequence_for<Values...>,
83 detail::index_sequence_for<Values...>,
89 template <std::size_t N, class ...T>
90 constexpr decltype(auto) get(tuple<T...>& t) noexcept {
91 static_assert(N < tuple<T...>::size_v, "====================> Boost.PFR: Tuple index out of bounds");
92 return sequence_tuple::get_impl<N>(t);
95 template <std::size_t N, class ...T>
96 constexpr decltype(auto) get(const tuple<T...>& t) noexcept {
97 static_assert(N < tuple<T...>::size_v, "====================> Boost.PFR: Tuple index out of bounds");
98 return sequence_tuple::get_impl<N>(t);
101 template <std::size_t N, class ...T>
102 constexpr decltype(auto) get(const volatile tuple<T...>& t) noexcept {
103 static_assert(N < tuple<T...>::size_v, "====================> Boost.PFR: Tuple index out of bounds");
104 return sequence_tuple::get_impl<N>(t);
107 template <std::size_t N, class ...T>
108 constexpr decltype(auto) get(volatile 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);
113 template <std::size_t N, class ...T>
114 constexpr decltype(auto) get(tuple<T...>&& t) noexcept {
115 static_assert(N < tuple<T...>::size_v, "====================> Boost.PFR: Tuple index out of bounds");
116 return sequence_tuple::get_impl<N>(std::move(t));
119 template <std::size_t I, class T>
120 using tuple_element = std::remove_reference< decltype(
121 ::boost::pfr::detail::sequence_tuple::get<I>( std::declval<T>() )
125 }}}} // namespace boost::pfr::detail::sequence_tuple
127 #endif // BOOST_PFR_CORE_HPP