Use rvalue or const lvalue references for some parameters
[alure.git] / include / mpark / lib.hpp
bloba9b3dee99e333e04f0184be4f1d460397feef82c
1 // MPark.Variant
2 //
3 // Copyright Michael Park, 2015-2017
4 //
5 // Distributed under the Boost Software License, Version 1.0.
6 // (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
8 #ifndef MPARK_LIB_HPP
9 #define MPARK_LIB_HPP
11 #include <memory>
12 #include <functional>
13 #include <type_traits>
14 #include <utility>
16 #include "config.hpp"
18 #define RETURN(...) \
19 noexcept(noexcept(__VA_ARGS__)) -> decltype(__VA_ARGS__) { \
20 return __VA_ARGS__; \
23 namespace mpark {
24 namespace lib {
25 template <typename T>
26 struct identity { using type = T; };
28 inline namespace cpp14 {
29 template <typename T, std::size_t N>
30 struct array {
31 constexpr const T &operator[](std::size_t index) const {
32 return data[index];
35 T data[N == 0 ? 1 : N];
38 template <typename T>
39 using add_pointer_t = typename std::add_pointer<T>::type;
41 template <typename... Ts>
42 using common_type_t = typename std::common_type<Ts...>::type;
44 template <typename T>
45 using decay_t = typename std::decay<T>::type;
47 template <bool B, typename T = void>
48 using enable_if_t = typename std::enable_if<B, T>::type;
50 template <typename T>
51 using remove_const_t = typename std::remove_const<T>::type;
53 template <typename T>
54 using remove_reference_t = typename std::remove_reference<T>::type;
56 template <typename T>
57 inline constexpr T &&forward(remove_reference_t<T> &t) noexcept {
58 return static_cast<T &&>(t);
61 template <typename T>
62 inline constexpr T &&forward(remove_reference_t<T> &&t) noexcept {
63 static_assert(!std::is_lvalue_reference<T>::value,
64 "can not forward an rvalue as an lvalue");
65 return static_cast<T &&>(t);
68 template <typename T>
69 inline constexpr remove_reference_t<T> &&move(T &&t) noexcept {
70 return static_cast<remove_reference_t<T> &&>(t);
73 #ifdef MPARK_INTEGER_SEQUENCE
74 using std::integer_sequence;
75 using std::index_sequence;
76 using std::make_index_sequence;
77 using std::index_sequence_for;
78 #else
79 template <typename T, T... Is>
80 struct integer_sequence {
81 using value_type = T;
82 static constexpr std::size_t size() noexcept { return sizeof...(Is); }
85 template <std::size_t... Is>
86 using index_sequence = integer_sequence<std::size_t, Is...>;
88 template <typename Lhs, typename Rhs>
89 struct make_index_sequence_concat;
91 template <std::size_t... Lhs, std::size_t... Rhs>
92 struct make_index_sequence_concat<index_sequence<Lhs...>,
93 index_sequence<Rhs...>>
94 : identity<index_sequence<Lhs..., (sizeof...(Lhs) + Rhs)...>> {};
96 template <std::size_t N>
97 struct make_index_sequence_impl;
99 template <std::size_t N>
100 using make_index_sequence = typename make_index_sequence_impl<N>::type;
102 template <std::size_t N>
103 struct make_index_sequence_impl
104 : make_index_sequence_concat<make_index_sequence<N / 2>,
105 make_index_sequence<N - (N / 2)>> {};
107 template <>
108 struct make_index_sequence_impl<0> : identity<index_sequence<>> {};
110 template <>
111 struct make_index_sequence_impl<1> : identity<index_sequence<0>> {};
113 template <typename... Ts>
114 using index_sequence_for = make_index_sequence<sizeof...(Ts)>;
115 #endif
117 // <functional>
118 #ifdef MPARK_TRANSPARENT_OPERATORS
119 using equal_to = std::equal_to<>;
120 #else
121 struct equal_to {
122 template <typename Lhs, typename Rhs>
123 inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const
124 RETURN(lib::forward<Lhs>(lhs) == lib::forward<Rhs>(rhs))
126 #endif
128 #ifdef MPARK_TRANSPARENT_OPERATORS
129 using not_equal_to = std::not_equal_to<>;
130 #else
131 struct not_equal_to {
132 template <typename Lhs, typename Rhs>
133 inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const
134 RETURN(lib::forward<Lhs>(lhs) != lib::forward<Rhs>(rhs))
136 #endif
138 #ifdef MPARK_TRANSPARENT_OPERATORS
139 using less = std::less<>;
140 #else
141 struct less {
142 template <typename Lhs, typename Rhs>
143 inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const
144 RETURN(lib::forward<Lhs>(lhs) < lib::forward<Rhs>(rhs))
146 #endif
148 #ifdef MPARK_TRANSPARENT_OPERATORS
149 using greater = std::greater<>;
150 #else
151 struct greater {
152 template <typename Lhs, typename Rhs>
153 inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const
154 RETURN(lib::forward<Lhs>(lhs) > lib::forward<Rhs>(rhs))
156 #endif
158 #ifdef MPARK_TRANSPARENT_OPERATORS
159 using less_equal = std::less_equal<>;
160 #else
161 struct less_equal {
162 template <typename Lhs, typename Rhs>
163 inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const
164 RETURN(lib::forward<Lhs>(lhs) <= lib::forward<Rhs>(rhs))
166 #endif
168 #ifdef MPARK_TRANSPARENT_OPERATORS
169 using greater_equal = std::greater_equal<>;
170 #else
171 struct greater_equal {
172 template <typename Lhs, typename Rhs>
173 inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const
174 RETURN(lib::forward<Lhs>(lhs) >= lib::forward<Rhs>(rhs))
176 #endif
177 } // namespace cpp14
179 inline namespace cpp17 {
181 // <type_traits>
182 template <bool B>
183 using bool_constant = std::integral_constant<bool, B>;
185 template <typename...>
186 struct voider : identity<void> {};
188 template <typename... Ts>
189 using void_t = typename voider<Ts...>::type;
191 namespace detail {
192 namespace swappable {
194 using std::swap;
196 template <typename T>
197 struct is_swappable_impl {
198 private:
199 template <typename U,
200 typename = decltype(swap(std::declval<U &>(),
201 std::declval<U &>()))>
202 inline static std::true_type test(int);
204 template <typename U>
205 inline static std::false_type test(...);
207 public:
208 using type = decltype(test<T>(0));
211 template <typename T>
212 using is_swappable = typename is_swappable_impl<T>::type;
214 template <typename T, bool = is_swappable<T>::value>
215 struct is_nothrow_swappable {
216 static constexpr bool value =
217 noexcept(swap(std::declval<T &>(), std::declval<T &>()));
220 template <typename T>
221 struct is_nothrow_swappable<T, false> : std::false_type {};
223 } // namespace swappable
224 } // namespace detail
226 template <typename T>
227 using is_swappable = detail::swappable::is_swappable<T>;
229 template <typename T>
230 using is_nothrow_swappable = detail::swappable::is_nothrow_swappable<T>;
232 // <functional>
233 #ifdef _MSC_VER
234 #pragma warning(push)
235 #pragma warning(disable : 4100)
236 #endif
237 template <typename F, typename... As>
238 inline constexpr auto invoke(F &&f, As &&... as)
239 RETURN(lib::forward<F>(f)(lib::forward<As>(as)...))
240 #ifdef _MSC_VER
241 #pragma warning(pop)
242 #endif
244 template <typename B, typename T, typename D>
245 inline constexpr auto invoke(T B::*pmv, D &&d)
246 RETURN(lib::forward<D>(d).*pmv)
248 template <typename Pmv, typename Ptr>
249 inline constexpr auto invoke(Pmv pmv, Ptr &&ptr)
250 RETURN((*lib::forward<Ptr>(ptr)).*pmv)
252 template <typename B, typename T, typename D, typename... As>
253 inline constexpr auto invoke(T B::*pmf, D &&d, As &&... as)
254 RETURN((lib::forward<D>(d).*pmf)(lib::forward<As>(as)...))
256 template <typename Pmf, typename Ptr, typename... As>
257 inline constexpr auto invoke(Pmf pmf, Ptr &&ptr, As &&... as)
258 RETURN(((*lib::forward<Ptr>(ptr)).*pmf)(lib::forward<As>(as)...))
260 namespace detail {
262 template <typename Void, typename, typename...>
263 struct invoke_result {};
265 template <typename F, typename... Args>
266 struct invoke_result<void_t<decltype(lib::invoke(
267 std::declval<F>(), std::declval<Args>()...))>,
269 Args...>
270 : identity<decltype(
271 lib::invoke(std::declval<F>(), std::declval<Args>()...))> {};
273 } // namespace detail
275 template <typename F, typename... Args>
276 using invoke_result = detail::invoke_result<void, F, Args...>;
278 template <typename F, typename... Args>
279 using invoke_result_t = typename invoke_result<F, Args...>::type;
281 namespace detail {
283 template <typename Void, typename, typename...>
284 struct is_invocable : std::false_type {};
286 template <typename F, typename... Args>
287 struct is_invocable<void_t<invoke_result_t<F, Args...>>, F, Args...>
288 : std::true_type {};
290 template <typename Void, typename, typename, typename...>
291 struct is_invocable_r : std::false_type {};
293 template <typename R, typename F, typename... Args>
294 struct is_invocable_r<void_t<invoke_result_t<F, Args...>>,
297 Args...>
298 : std::is_convertible<invoke_result_t<F, Args...>, R> {};
300 } // namespace detail
302 template <typename F, typename... Args>
303 using is_invocable = detail::is_invocable<void, F, Args...>;
305 template <typename R, typename F, typename... Args>
306 using is_invocable_r = detail::is_invocable_r<void, R, F, Args...>;
308 // <memory>
309 #ifdef MPARK_BUILTIN_ADDRESSOF
310 template <typename T>
311 inline constexpr T *addressof(T &arg) {
312 return __builtin_addressof(arg);
314 #else
315 namespace detail {
317 namespace has_addressof_impl {
319 struct fail;
321 template <typename T>
322 inline fail operator&(T &&);
324 template <typename T>
325 inline static constexpr bool impl() {
326 return (std::is_class<T>::value || std::is_union<T>::value) &&
327 !std::is_same<decltype(&std::declval<T &>()), fail>::value;
330 } // namespace has_addressof_impl
332 template <typename T>
333 using has_addressof = bool_constant<has_addressof_impl::impl<T>()>;
335 template <typename T>
336 inline constexpr T *addressof(T &arg, std::true_type) {
337 return std::addressof(arg);
340 template <typename T>
341 inline constexpr T *addressof(T &arg, std::false_type) {
342 return &arg;
345 } // namespace detail
347 template <typename T>
348 inline constexpr T *addressof(T &arg) {
349 return detail::addressof(arg, detail::has_addressof<T>{});
351 #endif
353 template <typename T>
354 inline constexpr T *addressof(const T &&) = delete;
356 } // namespace cpp17
358 template <typename T>
359 struct remove_all_extents : identity<T> {};
361 template <typename T, std::size_t N>
362 struct remove_all_extents<array<T, N>> : remove_all_extents<T> {};
364 template <typename T>
365 using remove_all_extents_t = typename remove_all_extents<T>::type;
367 template <std::size_t N>
368 using size_constant = std::integral_constant<std::size_t, N>;
370 template <bool... Bs>
371 using bool_sequence = integer_sequence<bool, Bs...>;
373 template <std::size_t I, typename T>
374 struct indexed_type : size_constant<I>, identity<T> {};
376 template <bool... Bs>
377 using all =
378 std::is_same<bool_sequence<true, Bs...>, bool_sequence<Bs..., true>>;
380 #ifdef MPARK_TYPE_PACK_ELEMENT
381 template <std::size_t I, typename... Ts>
382 using type_pack_element_t = __type_pack_element<I, Ts...>;
383 #else
384 template <std::size_t I, typename... Ts>
385 struct type_pack_element_impl {
386 private:
387 template <typename>
388 struct set;
390 template <std::size_t... Is>
391 struct set<index_sequence<Is...>> : indexed_type<Is, Ts>... {};
393 template <typename T>
394 inline static std::enable_if<true, T> impl(indexed_type<I, T>);
396 inline static std::enable_if<false> impl(...);
398 public:
399 using type = decltype(impl(set<index_sequence_for<Ts...>>{}));
402 template <std::size_t I, typename... Ts>
403 using type_pack_element = typename type_pack_element_impl<I, Ts...>::type;
405 template <std::size_t I, typename... Ts>
406 using type_pack_element_t = typename type_pack_element<I, Ts...>::type;
407 #endif
409 #ifdef MPARK_TRIVIALITY_TYPE_TRAITS
410 using std::is_trivially_copy_constructible;
411 using std::is_trivially_move_constructible;
412 using std::is_trivially_copy_assignable;
413 using std::is_trivially_move_assignable;
414 #else
415 template <typename T>
416 struct is_trivially_copy_constructible
417 : bool_constant<
418 std::is_copy_constructible<T>::value && __has_trivial_copy(T)> {};
420 template <typename T>
421 struct is_trivially_move_constructible : bool_constant<__is_trivial(T)> {};
423 template <typename T>
424 struct is_trivially_copy_assignable
425 : bool_constant<
426 std::is_copy_assignable<T>::value && __has_trivial_assign(T)> {};
428 template <typename T>
429 struct is_trivially_move_assignable : bool_constant<__is_trivial(T)> {};
430 #endif
432 } // namespace lib
433 } // namespace mpark
435 #undef RETURN
437 #endif // MPARK_LIB_HPP