]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // Copyright Louis Dionne 2013-2016 |
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> | |
15 | namespace hana = boost::hana; | |
16 | ||
17 | ||
18 | struct RefTuple { }; | |
19 | ||
20 | template <typename ...T> | |
21 | struct ref_tuple { | |
22 | hana::tuple<T&...> storage_; | |
23 | }; | |
24 | ||
25 | ||
26 | namespace boost { namespace hana { | |
27 | template <typename ...T> | |
28 | struct tag_of<ref_tuple<T...>> { | |
29 | using type = RefTuple; | |
30 | }; | |
31 | ||
32 | template <> | |
33 | struct make_impl<RefTuple> { | |
34 | template <typename ...T> | |
35 | static constexpr auto apply(T&& ...t) { | |
36 | return ref_tuple<T...>{{t...}}; | |
37 | } | |
38 | }; | |
39 | ||
40 | template <> | |
41 | struct at_impl<RefTuple> { | |
42 | template <typename Xs, typename N> | |
43 | static constexpr decltype(auto) apply(Xs&& xs, N const& n) { | |
44 | return hana::at(static_cast<Xs&&>(xs).storage_, n); | |
45 | } | |
46 | }; | |
47 | ||
48 | template <> | |
49 | struct is_empty_impl<RefTuple> { | |
50 | template <typename Xs> | |
51 | static constexpr auto apply(Xs const& xs) { | |
52 | return hana::is_empty(xs.storage_); | |
53 | } | |
54 | }; | |
55 | ||
56 | template <> | |
57 | struct drop_front_impl<RefTuple> { | |
58 | template <std::size_t n, typename T, typename ...U, std::size_t ...i> | |
59 | static constexpr auto helper(ref_tuple<T, U...> xs, std::index_sequence<i...>) { | |
60 | return hana::make<RefTuple>(hana::at_c<n + i>(xs.storage_)...); | |
61 | } | |
62 | ||
63 | template <typename ...T, typename N> | |
64 | static constexpr auto apply(ref_tuple<T...> xs, N const&) { | |
65 | return helper<N::value>(xs, std::make_index_sequence<( | |
66 | N::value < sizeof...(T) ? sizeof...(T) - N::value : 0 | |
67 | )>{}); | |
68 | } | |
69 | }; | |
70 | }} | |
71 | ||
72 | ||
73 | int main() { | |
74 | int i = 0, j = 1, k = 2; | |
75 | ||
76 | auto refs = hana::make<RefTuple>(i, j, k); | |
77 | hana::at_c<0>(refs) = 3; | |
78 | BOOST_HANA_RUNTIME_CHECK(i == 3); | |
79 | ||
80 | BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::is_empty(refs))); | |
81 | ||
82 | ref_tuple<int&, int&> tail = hana::drop_front(refs); | |
83 | hana::at_c<0>(tail) = 4; | |
84 | BOOST_HANA_RUNTIME_CHECK(j == 4); | |
85 | } |