]>
Commit | Line | Data |
---|---|---|
20effc67 TL |
1 | // Copyright (c) 2016-2020 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 | ||
6 | #ifndef BOOST_PFR_DETAIL_MAKE_FLAT_TUPLE_OF_REFERENCES_HPP | |
7 | #define BOOST_PFR_DETAIL_MAKE_FLAT_TUPLE_OF_REFERENCES_HPP | |
8 | #pragma once | |
9 | ||
10 | #include <boost/pfr/detail/config.hpp> | |
11 | ||
12 | #include <utility> // metaprogramming stuff | |
13 | #include <boost/pfr/detail/sequence_tuple.hpp> | |
14 | #include <boost/pfr/detail/rvalue_t.hpp> | |
15 | #include <boost/pfr/detail/make_integer_sequence.hpp> | |
16 | ||
17 | ||
18 | namespace boost { namespace pfr { namespace detail { | |
19 | ||
20 | template <std::size_t Index> | |
21 | using size_t_ = std::integral_constant<std::size_t, Index >; | |
22 | ||
23 | // Helper: Make a "getter" object corresponding to built-in tuple::get | |
24 | // For user-defined structures, the getter should be "offset_based_getter" | |
25 | struct sequence_tuple_getter { | |
26 | template <std::size_t idx, typename TupleOfReferences> | |
27 | decltype(auto) get(TupleOfReferences&& t, size_t_<idx>) const noexcept { | |
28 | return sequence_tuple::get<idx>(std::forward<TupleOfReferences>(t)); | |
29 | } | |
30 | }; | |
31 | ||
32 | ||
33 | template <class TupleOrUserType, class Getter, std::size_t Begin, std::size_t Size> | |
34 | constexpr auto make_flat_tuple_of_references(TupleOrUserType&, const Getter&, size_t_<Begin>, size_t_<Size>) noexcept; | |
35 | ||
36 | template <class TupleOrUserType, class Getter, std::size_t Begin> | |
37 | constexpr sequence_tuple::tuple<> make_flat_tuple_of_references(TupleOrUserType&, const Getter&, size_t_<Begin>, size_t_<0>) noexcept; | |
38 | ||
39 | template <class TupleOrUserType, class Getter, std::size_t Begin> | |
40 | constexpr auto make_flat_tuple_of_references(TupleOrUserType&, const Getter&, size_t_<Begin>, size_t_<1>) noexcept; | |
41 | ||
42 | template <class... T> | |
43 | constexpr auto tie_as_tuple_with_references(T&... args) noexcept { | |
44 | return sequence_tuple::tuple<T&...>{ args... }; | |
45 | } | |
46 | ||
47 | template <class... T> | |
48 | constexpr decltype(auto) tie_as_tuple_with_references(detail::sequence_tuple::tuple<T...>& t) noexcept { | |
49 | return detail::make_flat_tuple_of_references(t, sequence_tuple_getter{}, size_t_<0>{}, size_t_<sequence_tuple::tuple<T...>::size_v>{}); | |
50 | } | |
51 | ||
52 | template <class... T> | |
53 | constexpr decltype(auto) tie_as_tuple_with_references(const detail::sequence_tuple::tuple<T...>& t) noexcept { | |
54 | return detail::make_flat_tuple_of_references(t, sequence_tuple_getter{}, size_t_<0>{}, size_t_<sequence_tuple::tuple<T...>::size_v>{}); | |
55 | } | |
56 | ||
57 | template <class Tuple1, std::size_t... I1, class Tuple2, std::size_t... I2> | |
58 | constexpr auto my_tuple_cat_impl(const Tuple1& t1, std::index_sequence<I1...>, const Tuple2& t2, std::index_sequence<I2...>) noexcept { | |
59 | return detail::tie_as_tuple_with_references( | |
60 | sequence_tuple::get<I1>(t1)..., | |
61 | sequence_tuple::get<I2>(t2)... | |
62 | ); | |
63 | } | |
64 | ||
65 | template <class Tuple1, class Tuple2> | |
66 | constexpr auto my_tuple_cat(const Tuple1& t1, const Tuple2& t2) noexcept { | |
67 | return detail::my_tuple_cat_impl( | |
68 | t1, detail::make_index_sequence< Tuple1::size_v >{}, | |
69 | t2, detail::make_index_sequence< Tuple2::size_v >{} | |
70 | ); | |
71 | } | |
72 | ||
73 | template <class TupleOrUserType, class Getter, std::size_t Begin, std::size_t Size> | |
74 | constexpr auto make_flat_tuple_of_references(TupleOrUserType& t, const Getter& g, size_t_<Begin>, size_t_<Size>) noexcept { | |
75 | constexpr std::size_t next_size = Size / 2; | |
76 | return detail::my_tuple_cat( | |
77 | detail::make_flat_tuple_of_references(t, g, size_t_<Begin>{}, size_t_<next_size>{}), | |
78 | detail::make_flat_tuple_of_references(t, g, size_t_<Begin + Size / 2>{}, size_t_<Size - next_size>{}) | |
79 | ); | |
80 | } | |
81 | ||
82 | template <class TupleOrUserType, class Getter, std::size_t Begin> | |
83 | constexpr sequence_tuple::tuple<> make_flat_tuple_of_references(TupleOrUserType&, const Getter&, size_t_<Begin>, size_t_<0>) noexcept { | |
84 | return {}; | |
85 | } | |
86 | ||
87 | template <class TupleOrUserType, class Getter, std::size_t Begin> | |
88 | constexpr auto make_flat_tuple_of_references(TupleOrUserType& t, const Getter& g, size_t_<Begin>, size_t_<1>) noexcept { | |
89 | return detail::tie_as_tuple_with_references( | |
90 | g.get(t, size_t_<Begin>{}) | |
91 | ); | |
92 | } | |
93 | ||
94 | }}} // namespace boost::pfr::detail | |
95 | ||
96 | #endif // BOOST_PFR_DETAIL_MAKE_FLAT_TUPLE_OF_REFERENCES_HPP |