Merge pull request #40 from McSinyx/travis
[alure.git] / include / mpark / lib.hpp
blobc3efdd996171ff7795e258eecc5e0c88edc77f77
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 {
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 static constexpr bool value = decltype(test<T>(0))::value;
211 template <typename T, bool = is_swappable<T>::value>
212 struct is_nothrow_swappable {
213 static constexpr bool value =
214 noexcept(swap(std::declval<T &>(), std::declval<T &>()));
217 template <typename T>
218 struct is_nothrow_swappable<T, false> : std::false_type {};
220 } // namespace swappable
221 } // namespace detail
223 using detail::swappable::is_swappable;
224 using detail::swappable::is_nothrow_swappable;
226 // <functional>
227 #ifdef _MSC_VER
228 #pragma warning(push)
229 #pragma warning(disable : 4100)
230 #endif
231 template <typename F, typename... As>
232 inline constexpr auto invoke(F &&f, As &&... as)
233 RETURN(lib::forward<F>(f)(lib::forward<As>(as)...))
234 #ifdef _MSC_VER
235 #pragma warning(pop)
236 #endif
238 template <typename B, typename T, typename D>
239 inline constexpr auto invoke(T B::*pmv, D &&d)
240 RETURN(lib::forward<D>(d).*pmv)
242 template <typename Pmv, typename Ptr>
243 inline constexpr auto invoke(Pmv pmv, Ptr &&ptr)
244 RETURN((*lib::forward<Ptr>(ptr)).*pmv)
246 template <typename B, typename T, typename D, typename... As>
247 inline constexpr auto invoke(T B::*pmf, D &&d, As &&... as)
248 RETURN((lib::forward<D>(d).*pmf)(lib::forward<As>(as)...))
250 template <typename Pmf, typename Ptr, typename... As>
251 inline constexpr auto invoke(Pmf pmf, Ptr &&ptr, As &&... as)
252 RETURN(((*lib::forward<Ptr>(ptr)).*pmf)(lib::forward<As>(as)...))
254 namespace detail {
256 template <typename Void, typename, typename...>
257 struct invoke_result {};
259 template <typename F, typename... Args>
260 struct invoke_result<void_t<decltype(lib::invoke(
261 std::declval<F>(), std::declval<Args>()...))>,
263 Args...>
264 : identity<decltype(
265 lib::invoke(std::declval<F>(), std::declval<Args>()...))> {};
267 } // namespace detail
269 template <typename F, typename... Args>
270 using invoke_result = detail::invoke_result<void, F, Args...>;
272 template <typename F, typename... Args>
273 using invoke_result_t = typename invoke_result<F, Args...>::type;
275 namespace detail {
277 template <typename Void, typename, typename...>
278 struct is_invocable : std::false_type {};
280 template <typename F, typename... Args>
281 struct is_invocable<void_t<invoke_result_t<F, Args...>>, F, Args...>
282 : std::true_type {};
284 template <typename Void, typename, typename, typename...>
285 struct is_invocable_r : std::false_type {};
287 template <typename R, typename F, typename... Args>
288 struct is_invocable_r<void_t<invoke_result_t<F, Args...>>,
291 Args...>
292 : std::is_convertible<invoke_result_t<F, Args...>, R> {};
294 } // namespace detail
296 template <typename F, typename... Args>
297 using is_invocable = detail::is_invocable<void, F, Args...>;
299 template <typename R, typename F, typename... Args>
300 using is_invocable_r = detail::is_invocable_r<void, R, F, Args...>;
302 // <memory>
303 #ifdef MPARK_BUILTIN_ADDRESSOF
304 template <typename T>
305 inline constexpr T *addressof(T &arg) {
306 return __builtin_addressof(arg);
308 #else
309 namespace detail {
311 namespace has_addressof_impl {
313 struct fail;
315 template <typename T>
316 inline fail operator&(T &&);
318 template <typename T>
319 inline static constexpr bool impl() {
320 return (std::is_class<T>::value || std::is_union<T>::value) &&
321 !std::is_same<decltype(&std::declval<T &>()), fail>::value;
324 } // namespace has_addressof_impl
326 template <typename T>
327 using has_addressof = bool_constant<has_addressof_impl::impl<T>()>;
329 template <typename T>
330 inline constexpr T *addressof(T &arg, std::true_type) {
331 return std::addressof(arg);
334 template <typename T>
335 inline constexpr T *addressof(T &arg, std::false_type) {
336 return &arg;
339 } // namespace detail
341 template <typename T>
342 inline constexpr T *addressof(T &arg) {
343 return detail::addressof(arg, detail::has_addressof<T>{});
345 #endif
347 template <typename T>
348 inline constexpr T *addressof(const T &&) = delete;
350 } // namespace cpp17
352 template <typename T>
353 struct remove_all_extents : identity<T> {};
355 template <typename T, std::size_t N>
356 struct remove_all_extents<array<T, N>> : remove_all_extents<T> {};
358 template <typename T>
359 using remove_all_extents_t = typename remove_all_extents<T>::type;
361 template <std::size_t N>
362 using size_constant = std::integral_constant<std::size_t, N>;
364 template <std::size_t I, typename T>
365 struct indexed_type : size_constant<I>, identity<T> {};
367 template <bool... Bs>
368 using all = std::is_same<integer_sequence<bool, true, Bs...>,
369 integer_sequence<bool, Bs..., true>>;
371 #ifdef MPARK_TYPE_PACK_ELEMENT
372 template <std::size_t I, typename... Ts>
373 using type_pack_element_t = __type_pack_element<I, Ts...>;
374 #else
375 template <std::size_t I, typename... Ts>
376 struct type_pack_element_impl {
377 private:
378 template <typename>
379 struct set;
381 template <std::size_t... Is>
382 struct set<index_sequence<Is...>> : indexed_type<Is, Ts>... {};
384 template <typename T>
385 inline static std::enable_if<true, T> impl(indexed_type<I, T>);
387 inline static std::enable_if<false> impl(...);
389 public:
390 using type = decltype(impl(set<index_sequence_for<Ts...>>{}));
393 template <std::size_t I, typename... Ts>
394 using type_pack_element = typename type_pack_element_impl<I, Ts...>::type;
396 template <std::size_t I, typename... Ts>
397 using type_pack_element_t = typename type_pack_element<I, Ts...>::type;
398 #endif
400 #ifdef MPARK_TRIVIALITY_TYPE_TRAITS
401 using std::is_trivially_copy_constructible;
402 using std::is_trivially_move_constructible;
403 using std::is_trivially_copy_assignable;
404 using std::is_trivially_move_assignable;
405 #else
406 template <typename T>
407 struct is_trivially_copy_constructible
408 : bool_constant<
409 std::is_copy_constructible<T>::value && __has_trivial_copy(T)> {};
411 template <typename T>
412 struct is_trivially_move_constructible : bool_constant<__is_trivial(T)> {};
414 template <typename T>
415 struct is_trivially_copy_assignable
416 : bool_constant<
417 std::is_copy_assignable<T>::value && __has_trivial_assign(T)> {};
419 template <typename T>
420 struct is_trivially_move_assignable : bool_constant<__is_trivial(T)> {};
421 #endif
423 template <typename T, bool>
424 struct dependent_type : T {};
426 template <typename Is, std::size_t J>
427 struct push_back;
429 template <typename Is, std::size_t J>
430 using push_back_t = typename push_back<Is, J>::type;
432 template <std::size_t... Is, std::size_t J>
433 struct push_back<index_sequence<Is...>, J> {
434 using type = index_sequence<Is..., J>;
437 } // namespace lib
438 } // namespace mpark
440 #undef RETURN
442 #endif // MPARK_LIB_HPP