]>
Commit | Line | Data |
---|---|---|
b32b8144 | 1 | // Copyright Louis Dionne 2013-2017 |
7c673cae FG |
2 | // Distributed under the Boost Software License, Version 1.0. |
3 | // (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) | |
4 | ||
5 | #include <boost/hana/assert.hpp> | |
6 | #include <boost/hana/at.hpp> | |
7 | #include <boost/hana/core/make.hpp> | |
8 | #include <boost/hana/core/tag_of.hpp> | |
9 | #include <boost/hana/drop_front.hpp> | |
10 | #include <boost/hana/is_empty.hpp> | |
11 | #include <boost/hana/not.hpp> | |
12 | #include <boost/hana/tuple.hpp> | |
13 | ||
14 | #include <cstddef> | |
b32b8144 | 15 | #include <functional> |
7c673cae FG |
16 | namespace hana = boost::hana; |
17 | ||
18 | ||
b32b8144 FG |
19 | // A tuple that holds reference_wrappers to its elements, instead of the |
20 | // elements themselves. | |
21 | ||
7c673cae FG |
22 | struct RefTuple { }; |
23 | ||
24 | template <typename ...T> | |
b32b8144 FG |
25 | struct ref_tuple; |
26 | ||
27 | template <typename ...T> | |
28 | struct ref_tuple<T&...> { | |
29 | hana::tuple<std::reference_wrapper<T>...> storage_; | |
7c673cae FG |
30 | }; |
31 | ||
32 | ||
33 | namespace boost { namespace hana { | |
34 | template <typename ...T> | |
35 | struct tag_of<ref_tuple<T...>> { | |
36 | using type = RefTuple; | |
37 | }; | |
38 | ||
39 | template <> | |
40 | struct make_impl<RefTuple> { | |
41 | template <typename ...T> | |
b32b8144 FG |
42 | static constexpr auto apply(T& ...t) { |
43 | return ref_tuple<T&...>{{std::ref(t)...}}; | |
7c673cae FG |
44 | } |
45 | }; | |
46 | ||
47 | template <> | |
48 | struct at_impl<RefTuple> { | |
49 | template <typename Xs, typename N> | |
50 | static constexpr decltype(auto) apply(Xs&& xs, N const& n) { | |
b32b8144 | 51 | return hana::at(static_cast<Xs&&>(xs).storage_, n).get(); |
7c673cae FG |
52 | } |
53 | }; | |
54 | ||
55 | template <> | |
56 | struct is_empty_impl<RefTuple> { | |
57 | template <typename Xs> | |
58 | static constexpr auto apply(Xs const& xs) { | |
59 | return hana::is_empty(xs.storage_); | |
60 | } | |
61 | }; | |
62 | ||
63 | template <> | |
64 | struct drop_front_impl<RefTuple> { | |
65 | template <std::size_t n, typename T, typename ...U, std::size_t ...i> | |
66 | static constexpr auto helper(ref_tuple<T, U...> xs, std::index_sequence<i...>) { | |
b32b8144 | 67 | return hana::make<RefTuple>(hana::at_c<n + i>(xs.storage_).get()...); |
7c673cae FG |
68 | } |
69 | ||
70 | template <typename ...T, typename N> | |
71 | static constexpr auto apply(ref_tuple<T...> xs, N const&) { | |
72 | return helper<N::value>(xs, std::make_index_sequence<( | |
73 | N::value < sizeof...(T) ? sizeof...(T) - N::value : 0 | |
74 | )>{}); | |
75 | } | |
76 | }; | |
b32b8144 | 77 | }} // end namespace boost::hana |
7c673cae FG |
78 | |
79 | ||
80 | int main() { | |
81 | int i = 0, j = 1, k = 2; | |
82 | ||
b32b8144 | 83 | ref_tuple<int&, int&, int&> refs = hana::make<RefTuple>(i, j, k); |
7c673cae FG |
84 | hana::at_c<0>(refs) = 3; |
85 | BOOST_HANA_RUNTIME_CHECK(i == 3); | |
86 | ||
87 | BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::is_empty(refs))); | |
88 | ||
89 | ref_tuple<int&, int&> tail = hana::drop_front(refs); | |
90 | hana::at_c<0>(tail) = 4; | |
91 | BOOST_HANA_RUNTIME_CHECK(j == 4); | |
92 | } |