1 /*=============================================================================
2     Copyright (c) 2016 Paul Fultz II
3     unpack_tuple.hpp
4     Distributed under the Boost Software License, Version 1.0. (See accompanying
5     file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 ==============================================================================*/
7 
8 #ifndef BOOST_HOF_GUARD_UNPACK_TUPLE_HPP
9 #define BOOST_HOF_GUARD_UNPACK_TUPLE_HPP
10 
11 #include <boost/hof/unpack_sequence.hpp>
12 #include <boost/hof/returns.hpp>
13 #include <boost/hof/detail/forward.hpp>
14 #include <boost/hof/detail/seq.hpp>
15 #include <tuple>
16 #include <array>
17 
18 namespace boost { namespace hof {
19 
20 namespace detail {
21 
22 template<class Sequence>
23 constexpr typename gens<std::tuple_size<Sequence>::value>::type
make_tuple_gens(const Sequence &)24 make_tuple_gens(const Sequence&)
25 {
26     return {};
27 }
28 
29 #if (defined(__GNUC__) && !defined (__clang__) && __GNUC__ == 4 && __GNUC_MINOR__ < 7)
30 
31 template<std::size_t I, class Tuple>
32 struct tuple_element_return
33 : std::tuple_element<I, Tuple>
34 {};
35 
36 template<std::size_t I, class Tuple>
37 struct tuple_element_return<I, Tuple&>
38 : std::add_lvalue_reference<typename tuple_element_return<I, Tuple>::type>
39 {};
40 
41 template<std::size_t I, class Tuple>
42 struct tuple_element_return<I, Tuple&&>
43 : std::add_rvalue_reference<typename tuple_element_return<I, Tuple>::type>
44 {};
45 
46 template<std::size_t I, class Tuple>
47 struct tuple_element_return<I, const Tuple>
48 : std::add_const<typename tuple_element_return<I, Tuple>::type>
49 {};
50 
51 template< std::size_t I, class Tuple, class R = typename tuple_element_return<I, Tuple&&>::type >
tuple_get(Tuple && t)52 R tuple_get( Tuple&& t )
53 {
54     return (R&&)(std::get<I>(boost::hof::forward<Tuple>(t)));
55 }
56 #define BOOST_HOF_UNPACK_TUPLE_GET boost::hof::detail::tuple_get
57 #else
58 #define BOOST_HOF_UNPACK_TUPLE_GET std::get
59 
60 #endif
61 
62 template<class F, class T, std::size_t ...N>
63 constexpr auto unpack_tuple(F&& f, T&& t, seq<N...>) BOOST_HOF_RETURNS
64 (
65     f(
66         BOOST_HOF_AUTO_FORWARD(BOOST_HOF_UNPACK_TUPLE_GET<N>(BOOST_HOF_AUTO_FORWARD(t)))...
67     )
68 );
69 
70 struct unpack_tuple_apply
71 {
72     template<class F, class S>
73     constexpr static auto apply(F&& f, S&& t) BOOST_HOF_RETURNS
74     (
75         boost::hof::detail::unpack_tuple(BOOST_HOF_FORWARD(F)(f), BOOST_HOF_FORWARD(S)(t), boost::hof::detail::make_tuple_gens(t))
76     );
77 };
78 
79 }
80 
81 template<class... Ts>
82 struct unpack_sequence<std::tuple<Ts...>>
83 : detail::unpack_tuple_apply
84 {};
85 
86 template<class T, class U>
87 struct unpack_sequence<std::pair<T, U>>
88 : detail::unpack_tuple_apply
89 {};
90 
91 template<class T, std::size_t N>
92 struct unpack_sequence<std::array<T, N>>
93 : detail::unpack_tuple_apply
94 {};
95 
96 }} // namespace boost::hof
97 
98 #endif
99