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/at.hpp>
6 #include <boost/hana/at_key.hpp>
7 #include <boost/hana/back.hpp>
8 #include <boost/hana/front.hpp>
9 #include <boost/hana/integral_constant.hpp>
10 #include <boost/hana/tuple.hpp>
11 
12 #include <utility>
13 namespace hana = boost::hana;
14 
15 
16 template <typename T>
cref(T & t)17 T const& cref(T& t) { return t; }
18 
19 // a non-movable, non-copyable type
20 struct RefOnly {
21     RefOnly() = default;
22     RefOnly(RefOnly const&) = delete;
23     RefOnly(RefOnly&&) = delete;
24 };
25 
26 template <int i>
27 struct RefOnly_i : hana::int_<i> {
28     RefOnly_i() = default;
29     RefOnly_i(RefOnly_i const&) = delete;
30     RefOnly_i(RefOnly_i&&) = delete;
31 };
32 
main()33 int main() {
34     hana::tuple<RefOnly> t;
35 
36     // Make sure that we return the proper reference types from `at`.
37     {
38         RefOnly&& r1 = hana::at_c<0>(std::move(t));
39         RefOnly& r2 = hana::at_c<0>(t);
40         RefOnly const& r3 = hana::at_c<0>(cref(t));
41 
42         (void)r1; (void)r2; (void)r3;
43     }
44 
45     // Make sure we return the proper reference types from `front`.
46     {
47         RefOnly&& r1 = hana::front(std::move(t));
48         RefOnly& r2 = hana::front(t);
49         RefOnly const& r3 = hana::front(cref(t));
50 
51         (void)r1; (void)r2; (void)r3;
52     }
53 
54     // Make sure we return the proper reference types from `back`.
55     {
56         RefOnly&& r1 = hana::back(std::move(t));
57         RefOnly& r2 = hana::back(t);
58         RefOnly const& r3 = hana::back(cref(t));
59 
60         (void)r1; (void)r2; (void)r3;
61     }
62 
63     // Make sure we return the proper reference types from `at_key`.
64     {
65         hana::tuple<RefOnly_i<3>> t{};
66         RefOnly_i<3>& r1 = hana::at_key(t, RefOnly_i<3>{});
67         RefOnly_i<3> const& r2 = hana::at_key(cref(t), RefOnly_i<3>{});
68         RefOnly_i<3>&& r3 = hana::at_key(std::move(t), RefOnly_i<3>{});
69 
70         (void)r1; (void)r2; (void)r3;
71     }
72 }
73