Backport
tuple.hpp
Go to the documentation of this file.
1 
7 /*
8  The MIT License (MIT)
9 
10  Copyright (c) 2020 Matthew Rodusek All rights reserved.
11 
12  Permission is hereby granted, free of charge, to any person obtaining a copy
13  of this software and associated documentation files (the "Software"), to deal
14  in the Software without restriction, including without limitation the rights
15  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16  copies of the Software, and to permit persons to whom the Software is
17  furnished to do so, subject to the following conditions:
18 
19  The above copyright notice and this permission notice shall be included in
20  all copies or substantial portions of the Software.
21 
22  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28  SOFTWARE.
29 */
30 #ifndef BPSTD_TUPLE_HPP
31 #define BPSTD_TUPLE_HPP
32 
33 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
34 # pragma once
35 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
36 
37 #include "type_traits.hpp" // invoke_result
38 #include "utility.hpp" // index_sequence, forward
39 #include "functional.hpp" // invoke
40 
41 #include <tuple> // std::tuple_element, and to proxy API
42 #include <cstddef> // std::size_t
43 
44 BPSTD_COMPILER_DIAGNOSTIC_PREAMBLE
45 
46 namespace bpstd {
47 
48  //============================================================================
49  // class : tuple
50  //============================================================================
51 
52  template <typename...Types>
53  using tuple = std::tuple<Types...>;
54 
55  //============================================================================
56  // utilities : tuple
57  //============================================================================
58 
59  template <std::size_t I, typename T>
60  using tuple_element = std::tuple_element<I,T>;
61 
62  template <std::size_t I, typename T>
63  using tuple_element_t = typename tuple_element<I, T>::type;
64 
65  //----------------------------------------------------------------------------
66 
67  template <typename T>
68  using tuple_size = std::tuple_size<T>;
69 
70 #if BPSTD_HAS_TEMPLATE_VARIABLES
71  template <typename T>
72  BPSTD_CPP17_INLINE constexpr auto tuple_size_v = tuple_size<T>::value;
73 #endif
74 
75  //============================================================================
76  // non-member functions : class : tuple
77  //============================================================================
78 
79  //----------------------------------------------------------------------------
80  // Utilities
81  //----------------------------------------------------------------------------
82 
83  namespace detail {
84  template <typename T>
85  struct is_tuple : false_type{};
86 
87  template <typename...Types>
88  struct is_tuple<std::tuple<Types...>> : true_type{};
89  } // namespace detail
90 
91  template <std::size_t N, typename Tuple,
92  typename = enable_if_t<detail::is_tuple<remove_cvref_t<Tuple>>::value && is_lvalue_reference<Tuple>::value>>
93  inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR
94  tuple_element_t<N,remove_reference_t<Tuple>>&
95  get(Tuple&& t) noexcept
96  {
97  return std::get<N>(t);
98  }
99 
100  template <std::size_t N, typename Tuple,
101  typename = enable_if_t<detail::is_tuple<remove_cvref_t<Tuple>>::value && !is_lvalue_reference<Tuple>::value>>
102  inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR
103  tuple_element_t<N,remove_reference_t<Tuple>>&&
104  get(Tuple&& t) noexcept
105  {
106  return bpstd::move(std::get<N>(t));
107  }
108 
109  template <typename T, typename... Types>
110  BPSTD_CPP14_CONSTEXPR T& get(tuple<Types...>& t) noexcept;
111  template <typename T, typename... Types>
112  BPSTD_CPP14_CONSTEXPR T&& get(tuple<Types...>&& t) noexcept;
113  template <typename T, typename... Types>
114  BPSTD_CPP14_CONSTEXPR const T& get(const tuple<Types...>& t) noexcept;
115  template <typename T, typename... Types>
116  BPSTD_CPP14_CONSTEXPR const T&& get(const tuple<Types...>&& t) noexcept;
117 
118  //----------------------------------------------------------------------------
119 
120  namespace detail {
121 
122  // primary template left undefined
123  template <typename Fn, typename Seq, typename Tuple>
124  struct apply_result_impl;
125 
126  template <typename Fn, std::size_t...Idx, typename Tuple>
127  struct apply_result_impl<Fn, index_sequence<Idx...>, Tuple>
128  : invoke_result<Fn, tuple_element_t<Idx, Tuple>...>{};
129 
130  template <typename Fn, typename Tuple>
131  struct apply_result : apply_result_impl<
132  Fn,
133  make_index_sequence<tuple_size<remove_reference_t<Tuple>>::value>,
134  Tuple
135  >{};
136 
137  template <typename Fn, typename Tuple>
138  using apply_result_t = typename apply_result<Fn, Tuple>::type;
139  } // namespace detail
140 
149  template <typename Fn, typename Tuple>
150  constexpr detail::apply_result_t<Fn, Tuple> apply(Fn&& fn, Tuple&& tuple);
151 
156  template <typename T, typename Tuple>
157  constexpr T make_from_tuple(Tuple&& tuple);
158 
159 } // namespace bpstd
160 
161 //==============================================================================
162 // definitions : non-member functions : class : tuple
163 //==============================================================================
164 
165 //------------------------------------------------------------------------------
166 // Utilities
167 //------------------------------------------------------------------------------
168 
169 namespace bpstd { namespace detail {
170 
171  template <typename T, std::size_t Index, typename...Types>
172  struct index_of_impl;
173 
174  template <typename T, std::size_t Index, typename Type0, typename...Types>
175  struct index_of_impl<T, Index, Type0, Types...>
176  : index_of_impl<T, Index + 1, Types...>{};
177 
178  template <typename T, std::size_t Index, typename...Types>
179  struct index_of_impl<T, Index, T, Types...>
180  : integral_constant<std::size_t, Index>{};
181 
182  template <typename T, typename...Types>
183  struct index_of : index_of_impl<T,0,Types...>{};
184 
185 }} // namespace bpstd::detail
186 
187 template <typename T, typename... Types>
188 inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR
189 T& bpstd::get(tuple<Types...>& t)
190  noexcept
191 {
192  return std::get<detail::index_of<T,Types...>::value>(t);
193 }
194 
195 template <typename T, typename... Types>
196 inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR
197 T&& bpstd::get(tuple<Types...>&& t)
198  noexcept
199 {
200  return move(std::get<detail::index_of<T,Types...>::value>(t));
201 }
202 
203 template <typename T, typename... Types>
204 inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR
205 const T& bpstd::get(const tuple<Types...>& t)
206  noexcept
207 {
208  return std::get<detail::index_of<T,Types...>::value>(t);
209 }
210 
211 template <typename T, typename... Types>
212 inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR
213 const T&& bpstd::get(const tuple<Types...>&& t)
214  noexcept
215 {
216  return move(std::get<detail::index_of<T,Types...>::value>(t));
217 }
218 
219 //==============================================================================
220 // definition : apply
221 //==============================================================================
222 
223 #if defined(_MSC_VER)
224 # pragma warning(push)
225 # pragma warning(disable:4100) // MSVC warns that 'tuple' is not used below
226 #endif
227 
228 namespace bpstd {
229  namespace detail {
230  template <typename Fn, typename Tuple, std::size_t... I>
231  inline BPSTD_INLINE_VISIBILITY constexpr
232  apply_result_t<Fn,Tuple> apply_impl(Fn&& fn, Tuple&& tuple, index_sequence<I...>)
233  {
234  return ::bpstd::invoke(
235  bpstd::forward<Fn>(fn),
236  std::get<I>(bpstd::forward<Tuple>(tuple))...
237  );
238  }
239  } // namespace detail
240 } // namespace bpstd
241 
242 #if defined(_MSC_VER)
243 # pragma warning(pop)
244 #endif
245 
246 template <typename Fn, typename Tuple>
247 inline BPSTD_INLINE_VISIBILITY constexpr
248 bpstd::detail::apply_result_t<Fn, Tuple> bpstd::apply(Fn&& fn, Tuple&& tuple)
249 {
250  return detail::apply_impl(
251  bpstd::forward<Fn>(fn),
252  bpstd::forward<Tuple>(tuple),
253  make_index_sequence<tuple_size<remove_reference_t<Tuple>>::value>{}
254  );
255 }
256 
257 //==============================================================================
258 // definition : make_from_tuple
259 //==============================================================================
260 
261 #if defined(_MSC_VER)
262 # pragma warning(push)
263 # pragma warning(disable:4100) // MSVC warns that 'tuple' is not used below
264 #endif
265 
266 namespace bpstd {
267  namespace detail {
268  template <typename T, typename Tuple, std::size_t... I>
269  inline BPSTD_INLINE_VISIBILITY constexpr
270  T make_from_tuple_impl(Tuple&& tuple, index_sequence<I...>)
271  {
272  return T(std::get<I>(bpstd::forward<Tuple>(tuple))...);
273  }
274  } // namespace detail
275 } // namespace bpstd
276 
277 #if defined(_MSC_VER)
278 # pragma warning(pop)
279 #endif
280 
281 template <typename T, typename Tuple>
282 inline BPSTD_INLINE_VISIBILITY constexpr
283 T bpstd::make_from_tuple(Tuple&& tuple)
284 {
285  return detail::make_from_tuple_impl<T>(
286  bpstd::forward<Tuple>(tuple),
287  make_index_sequence<tuple_size<remove_reference_t<Tuple>>::value>{}
288  );
289 }
290 
291 BPSTD_COMPILER_DIAGNOSTIC_POSTAMBLE
292 
293 #endif /* BPSTD_TUPLE_HPP */
bpstd::apply
constexpr detail::apply_result_t< Fn, Tuple > apply(Fn &&fn, Tuple &&tuple)
Invokes the function fn using the arguments in tuple.
type_traits.hpp
This header provides definitions from the C++ header <type_traits>
bpstd::get
const BPSTD_CPP14_CONSTEXPR T && get(const variant< Types... > &&v)
Gets the underlying element of the variant with the specified type.
functional.hpp
This header provides definitions from the C++ header <functional>
bpstd::make_from_tuple
constexpr T make_from_tuple(Tuple &&tuple)
Constructs a type T using the arguments in tuple.
utility.hpp
This header provides definitions from the C++ header <utility>