Imported Upstream version 2.99.2
[platform/upstream/libsigc++.git] / sigc++ / tuple-utils / tuple_start.h
1 /* Copyright (C) 2016 Murray Cumming
2  *
3  * This program is free software: you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License as published by
5  * the Free Software Foundation, either version 3 of the License, or
6  *  (at your option) any later version.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program.  If not, see <http://www.gnu.org/licenses/
15  */
16
17 #ifndef SIGC_TUPLE_UTILS_TUPLE_START_H
18 #define SIGC_TUPLE_UTILS_TUPLE_START_H
19
20 #include <tuple>
21 #include <utility>
22
23 namespace sigc {
24
25 namespace internal {
26
27 namespace detail {
28
29 template <typename T, typename Seq>
30 struct tuple_type_start_impl;
31
32 template <typename T, std::size_t... I>
33 struct tuple_type_start_impl<T, std::index_sequence<I...>> {
34   using type = std::tuple<typename std::tuple_element<I, T>::type...>;
35 };
36
37 } // detail namespace
38
39 /**
40  * Get the type of a tuple with just the first @len items.
41  */
42 template <typename T, std::size_t len>
43 struct tuple_type_start
44   : detail::tuple_type_start_impl<T, std::make_index_sequence<len>> {};
45
46 namespace detail {
47
48 template <typename T, typename Seq>
49 struct tuple_start_impl;
50
51 template <typename T, std::size_t... I>
52 struct tuple_start_impl<T, std::index_sequence<I...>> {
53   static
54   constexpr
55   decltype(auto)
56   tuple_start(T&& t) {
57     constexpr auto size = std::tuple_size<std::decay_t<T>>::value;
58     constexpr auto len = sizeof...(I);
59     static_assert(len <= size, "The tuple size must be less than or equal to the length.");
60
61     using start = typename tuple_type_start<std::decay_t<T>, len>::type;
62     return start(std::get<I>(std::forward<T>(t))...);
63   }
64 };
65
66 } // detail namespace
67
68 /**
69  * Get the tuple with the last @a len items of the original.
70  */
71 template <std::size_t len, typename T>
72 constexpr
73 decltype(auto) // typename tuple_type_end<T, len>::type
74 tuple_start(T&& t) {
75   //We use std::decay_t<> because tuple_size is not defined for references.
76   constexpr auto size = std::tuple_size<std::decay_t<T>>::value;
77   static_assert(len <= size, "The tuple size must be less than or equal to the length.");
78
79   return detail::tuple_start_impl<T, std::make_index_sequence<len>>::tuple_start(
80     std::forward<T>(t));
81 }
82
83 } // namespace internal
84
85 } // namespace sigc
86
87 #endif //SIGC_TUPLE_UTILS_TUPLE_START_H