• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright Louis Dionne 2013-2017
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 #include <functional>
16 namespace hana = boost::hana;
17 
18 
19 // A tuple that holds reference_wrappers to its elements, instead of the
20 // elements themselves.
21 
22 struct RefTuple { };
23 
24 template <typename ...T>
25 struct ref_tuple;
26 
27 template <typename ...T>
28 struct ref_tuple<T&...> {
29     hana::tuple<std::reference_wrapper<T>...> storage_;
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>
applyboost::hana::make_impl42         static constexpr auto apply(T& ...t) {
43             return ref_tuple<T&...>{{std::ref(t)...}};
44         }
45     };
46 
47     template <>
48     struct at_impl<RefTuple> {
49         template <typename Xs, typename N>
applyboost::hana::at_impl50         static constexpr decltype(auto) apply(Xs&& xs, N const& n) {
51             return hana::at(static_cast<Xs&&>(xs).storage_, n).get();
52         }
53     };
54 
55     template <>
56     struct is_empty_impl<RefTuple> {
57         template <typename Xs>
applyboost::hana::is_empty_impl58         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>
helperboost::hana::drop_front_impl66         static constexpr auto helper(ref_tuple<T, U...> xs, std::index_sequence<i...>) {
67             return hana::make<RefTuple>(hana::at_c<n + i>(xs.storage_).get()...);
68         }
69 
70         template <typename ...T, typename N>
applyboost::hana::drop_front_impl71         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     };
77 }} // end namespace boost::hana
78 
79 
main()80 int main() {
81     int i = 0, j = 1, k = 2;
82 
83     ref_tuple<int&, int&, int&> refs = hana::make<RefTuple>(i, j, k);
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 }
93