| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537 |
- // MPark.Variant
- //
- // Copyright Michael Park, 2015-2017
- //
- // Distributed under the Boost Software License, Version 1.0.
- // (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
- #ifndef MPARK_LIB_HPP
- #define MPARK_LIB_HPP
- #include <memory>
- #include <functional>
- #include <type_traits>
- #include <utility>
- #include "config.hpp"
- #define MPARK_RETURN(...) \
- noexcept(noexcept(__VA_ARGS__)) -> decltype(__VA_ARGS__) { return __VA_ARGS__; }
- namespace mpark {
- namespace lib {
- template <typename T>
- struct identity { using type = T; };
- inline namespace cpp14 {
- template <typename T, std::size_t N>
- struct array {
- constexpr const T &operator[](std::size_t index) const {
- return data[index];
- }
- T data[N == 0 ? 1 : N];
- };
- template <typename T>
- using add_pointer_t = typename std::add_pointer<T>::type;
- template <typename... Ts>
- using common_type_t = typename std::common_type<Ts...>::type;
- template <typename T>
- using decay_t = typename std::decay<T>::type;
- template <bool B, typename T = void>
- using enable_if_t = typename std::enable_if<B, T>::type;
- template <typename T>
- using remove_const_t = typename std::remove_const<T>::type;
- template <typename T>
- using remove_reference_t = typename std::remove_reference<T>::type;
- template <typename T>
- inline constexpr T &&forward(remove_reference_t<T> &t) noexcept {
- return static_cast<T &&>(t);
- }
- template <typename T>
- inline constexpr T &&forward(remove_reference_t<T> &&t) noexcept {
- static_assert(!std::is_lvalue_reference<T>::value,
- "can not forward an rvalue as an lvalue");
- return static_cast<T &&>(t);
- }
- template <typename T>
- inline constexpr remove_reference_t<T> &&move(T &&t) noexcept {
- return static_cast<remove_reference_t<T> &&>(t);
- }
- #ifdef MPARK_INTEGER_SEQUENCE
- using std::integer_sequence;
- using std::index_sequence;
- using std::make_index_sequence;
- using std::index_sequence_for;
- #else
- template <typename T, T... Is>
- struct integer_sequence {
- using value_type = T;
- static constexpr std::size_t size() noexcept { return sizeof...(Is); }
- };
- template <std::size_t... Is>
- using index_sequence = integer_sequence<std::size_t, Is...>;
- template <typename Lhs, typename Rhs>
- struct make_index_sequence_concat;
- template <std::size_t... Lhs, std::size_t... Rhs>
- struct make_index_sequence_concat<index_sequence<Lhs...>,
- index_sequence<Rhs...>>
- : identity<index_sequence<Lhs..., (sizeof...(Lhs) + Rhs)...>> {};
- template <std::size_t N>
- struct make_index_sequence_impl;
- template <std::size_t N>
- using make_index_sequence = typename make_index_sequence_impl<N>::type;
- template <std::size_t N>
- struct make_index_sequence_impl
- : make_index_sequence_concat<make_index_sequence<N / 2>,
- make_index_sequence<N - (N / 2)>> {};
- template <>
- struct make_index_sequence_impl<0> : identity<index_sequence<>> {};
- template <>
- struct make_index_sequence_impl<1> : identity<index_sequence<0>> {};
- template <typename... Ts>
- using index_sequence_for = make_index_sequence<sizeof...(Ts)>;
- #endif
- // <functional>
- #ifdef MPARK_TRANSPARENT_OPERATORS
- using equal_to = std::equal_to<>;
- #else
- struct equal_to {
- template <typename Lhs, typename Rhs>
- inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const
- MPARK_RETURN(lib::forward<Lhs>(lhs) == lib::forward<Rhs>(rhs))
- };
- #endif
- #ifdef MPARK_TRANSPARENT_OPERATORS
- using not_equal_to = std::not_equal_to<>;
- #else
- struct not_equal_to {
- template <typename Lhs, typename Rhs>
- inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const
- MPARK_RETURN(lib::forward<Lhs>(lhs) != lib::forward<Rhs>(rhs))
- };
- #endif
- #ifdef MPARK_TRANSPARENT_OPERATORS
- using less = std::less<>;
- #else
- struct less {
- template <typename Lhs, typename Rhs>
- inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const
- MPARK_RETURN(lib::forward<Lhs>(lhs) < lib::forward<Rhs>(rhs))
- };
- #endif
- #ifdef MPARK_TRANSPARENT_OPERATORS
- using greater = std::greater<>;
- #else
- struct greater {
- template <typename Lhs, typename Rhs>
- inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const
- MPARK_RETURN(lib::forward<Lhs>(lhs) > lib::forward<Rhs>(rhs))
- };
- #endif
- #ifdef MPARK_TRANSPARENT_OPERATORS
- using less_equal = std::less_equal<>;
- #else
- struct less_equal {
- template <typename Lhs, typename Rhs>
- inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const
- MPARK_RETURN(lib::forward<Lhs>(lhs) <= lib::forward<Rhs>(rhs))
- };
- #endif
- #ifdef MPARK_TRANSPARENT_OPERATORS
- using greater_equal = std::greater_equal<>;
- #else
- struct greater_equal {
- template <typename Lhs, typename Rhs>
- inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const
- MPARK_RETURN(lib::forward<Lhs>(lhs) >= lib::forward<Rhs>(rhs))
- };
- #endif
- } // namespace cpp14
- inline namespace cpp17 {
- // <type_traits>
- template <bool B>
- using bool_constant = std::integral_constant<bool, B>;
- template <typename...>
- struct voider : identity<void> {};
- template <typename... Ts>
- using void_t = typename voider<Ts...>::type;
- namespace detail {
- namespace swappable {
- using std::swap;
- template <typename T>
- struct is_swappable {
- private:
- template <typename U,
- typename = decltype(swap(std::declval<U &>(),
- std::declval<U &>()))>
- inline static std::true_type test(int);
- template <typename U>
- inline static std::false_type test(...);
- public:
- static constexpr bool value = decltype(test<T>(0))::value;
- };
- template <bool IsSwappable, typename T>
- struct is_nothrow_swappable {
- static constexpr bool value =
- noexcept(swap(std::declval<T &>(), std::declval<T &>()));
- };
- template <typename T>
- struct is_nothrow_swappable<false, T> : std::false_type {};
- } // namespace swappable
- } // namespace detail
- using detail::swappable::is_swappable;
- template <typename T>
- using is_nothrow_swappable =
- detail::swappable::is_nothrow_swappable<is_swappable<T>::value, T>;
- // <functional>
- namespace detail {
- template <typename T>
- struct is_reference_wrapper : std::false_type {};
- template <typename T>
- struct is_reference_wrapper<std::reference_wrapper<T>>
- : std::true_type {};
- template <bool, int>
- struct Invoke;
- template <>
- struct Invoke<true /* pmf */, 0 /* is_base_of */> {
- template <typename R, typename T, typename Arg, typename... Args>
- inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&... args)
- MPARK_RETURN((lib::forward<Arg>(arg).*pmf)(lib::forward<Args>(args)...))
- };
- template <>
- struct Invoke<true /* pmf */, 1 /* is_reference_wrapper */> {
- template <typename R, typename T, typename Arg, typename... Args>
- inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&... args)
- MPARK_RETURN((lib::forward<Arg>(arg).get().*pmf)(lib::forward<Args>(args)...))
- };
- template <>
- struct Invoke<true /* pmf */, 2 /* otherwise */> {
- template <typename R, typename T, typename Arg, typename... Args>
- inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&... args)
- MPARK_RETURN(((*lib::forward<Arg>(arg)).*pmf)(lib::forward<Args>(args)...))
- };
- template <>
- struct Invoke<false /* pmo */, 0 /* is_base_of */> {
- template <typename R, typename T, typename Arg>
- inline static constexpr auto invoke(R T::*pmo, Arg &&arg)
- MPARK_RETURN(lib::forward<Arg>(arg).*pmo)
- };
- template <>
- struct Invoke<false /* pmo */, 1 /* is_reference_wrapper */> {
- template <typename R, typename T, typename Arg>
- inline static constexpr auto invoke(R T::*pmo, Arg &&arg)
- MPARK_RETURN(lib::forward<Arg>(arg).get().*pmo)
- };
- template <>
- struct Invoke<false /* pmo */, 2 /* otherwise */> {
- template <typename R, typename T, typename Arg>
- inline static constexpr auto invoke(R T::*pmo, Arg &&arg)
- MPARK_RETURN((*lib::forward<Arg>(arg)).*pmo)
- };
- template <typename R, typename T, typename Arg, typename... Args>
- inline constexpr auto invoke(R T::*f, Arg &&arg, Args &&... args)
- MPARK_RETURN(
- Invoke<std::is_function<R>::value,
- (std::is_base_of<T, lib::decay_t<Arg>>::value
- ? 0
- : is_reference_wrapper<lib::decay_t<Arg>>::value
- ? 1
- : 2)>::invoke(f,
- lib::forward<Arg>(arg),
- lib::forward<Args>(args)...))
- #ifdef _MSC_VER
- #pragma warning(push)
- #pragma warning(disable : 4100)
- #endif
- template <typename F, typename... Args>
- inline constexpr auto invoke(F &&f, Args &&... args)
- MPARK_RETURN(lib::forward<F>(f)(lib::forward<Args>(args)...))
- #ifdef _MSC_VER
- #pragma warning(pop)
- #endif
- } // namespace detail
- template <typename F, typename... Args>
- inline constexpr auto invoke(F &&f, Args &&... args)
- MPARK_RETURN(detail::invoke(lib::forward<F>(f),
- lib::forward<Args>(args)...))
- namespace detail {
- template <typename Void, typename, typename...>
- struct invoke_result {};
- template <typename F, typename... Args>
- struct invoke_result<void_t<decltype(lib::invoke(
- std::declval<F>(), std::declval<Args>()...))>,
- F,
- Args...>
- : identity<decltype(
- lib::invoke(std::declval<F>(), std::declval<Args>()...))> {};
- } // namespace detail
- template <typename F, typename... Args>
- using invoke_result = detail::invoke_result<void, F, Args...>;
- template <typename F, typename... Args>
- using invoke_result_t = typename invoke_result<F, Args...>::type;
- namespace detail {
- template <typename Void, typename, typename...>
- struct is_invocable : std::false_type {};
- template <typename F, typename... Args>
- struct is_invocable<void_t<invoke_result_t<F, Args...>>, F, Args...>
- : std::true_type {};
- template <typename Void, typename, typename, typename...>
- struct is_invocable_r : std::false_type {};
- template <typename R, typename F, typename... Args>
- struct is_invocable_r<void_t<invoke_result_t<F, Args...>>,
- R,
- F,
- Args...>
- : std::is_convertible<invoke_result_t<F, Args...>, R> {};
- } // namespace detail
- template <typename F, typename... Args>
- using is_invocable = detail::is_invocable<void, F, Args...>;
- template <typename R, typename F, typename... Args>
- using is_invocable_r = detail::is_invocable_r<void, R, F, Args...>;
- namespace detail {
- template <bool Invocable, typename F, typename... Args>
- struct is_nothrow_invocable {
- static constexpr bool value =
- noexcept(lib::invoke(std::declval<F>(), std::declval<Args>()...));
- };
- template <typename F, typename... Args>
- struct is_nothrow_invocable<false, F, Args...> : std::false_type {};
- template <bool Invocable, typename R, typename F, typename... Args>
- struct is_nothrow_invocable_r {
- private:
- inline static R impl() {
- return lib::invoke(std::declval<F>(), std::declval<Args>()...);
- }
- public:
- static constexpr bool value = noexcept(impl());
- };
- template <typename R, typename F, typename... Args>
- struct is_nothrow_invocable_r<false, R, F, Args...> : std::false_type {};
- } // namespace detail
- template <typename F, typename... Args>
- using is_nothrow_invocable = detail::
- is_nothrow_invocable<is_invocable<F, Args...>::value, F, Args...>;
- template <typename R, typename F, typename... Args>
- using is_nothrow_invocable_r =
- detail::is_nothrow_invocable_r<is_invocable_r<R, F, Args...>::value,
- R,
- F,
- Args...>;
- // <memory>
- #ifdef MPARK_BUILTIN_ADDRESSOF
- template <typename T>
- inline constexpr T *addressof(T &arg) noexcept {
- return __builtin_addressof(arg);
- }
- #else
- namespace detail {
- namespace has_addressof_impl {
- struct fail;
- template <typename T>
- inline fail operator&(T &&);
- template <typename T>
- inline static constexpr bool impl() {
- return (std::is_class<T>::value || std::is_union<T>::value) &&
- !std::is_same<decltype(&std::declval<T &>()), fail>::value;
- }
- } // namespace has_addressof_impl
- template <typename T>
- using has_addressof = bool_constant<has_addressof_impl::impl<T>()>;
- template <typename T>
- inline constexpr T *addressof(T &arg, std::true_type) noexcept {
- return std::addressof(arg);
- }
- template <typename T>
- inline constexpr T *addressof(T &arg, std::false_type) noexcept {
- return &arg;
- }
- } // namespace detail
- template <typename T>
- inline constexpr T *addressof(T &arg) noexcept {
- return detail::addressof(arg, detail::has_addressof<T>{});
- }
- #endif
- template <typename T>
- inline constexpr T *addressof(const T &&) = delete;
- } // namespace cpp17
- template <typename T>
- struct remove_all_extents : identity<T> {};
- template <typename T, std::size_t N>
- struct remove_all_extents<array<T, N>> : remove_all_extents<T> {};
- template <typename T>
- using remove_all_extents_t = typename remove_all_extents<T>::type;
- template <std::size_t N>
- using size_constant = std::integral_constant<std::size_t, N>;
- template <std::size_t I, typename T>
- struct indexed_type : size_constant<I> { using type = T; };
- template <bool... Bs>
- using all = std::is_same<integer_sequence<bool, true, Bs...>,
- integer_sequence<bool, Bs..., true>>;
- #ifdef MPARK_TYPE_PACK_ELEMENT
- template <std::size_t I, typename... Ts>
- using type_pack_element_t = __type_pack_element<I, Ts...>;
- #else
- template <std::size_t I, typename... Ts>
- struct type_pack_element_impl {
- private:
- template <typename>
- struct set;
- template <std::size_t... Is>
- struct set<index_sequence<Is...>> : indexed_type<Is, Ts>... {};
- template <typename T>
- inline static std::enable_if<true, T> impl(indexed_type<I, T>);
- inline static std::enable_if<false> impl(...);
- public:
- using type = decltype(impl(set<index_sequence_for<Ts...>>{}));
- };
- template <std::size_t I, typename... Ts>
- using type_pack_element = typename type_pack_element_impl<I, Ts...>::type;
- template <std::size_t I, typename... Ts>
- using type_pack_element_t = typename type_pack_element<I, Ts...>::type;
- #endif
- #ifdef MPARK_TRIVIALITY_TYPE_TRAITS
- using std::is_trivially_copy_constructible;
- using std::is_trivially_move_constructible;
- using std::is_trivially_copy_assignable;
- using std::is_trivially_move_assignable;
- #else
- template <typename T>
- struct is_trivially_copy_constructible
- : bool_constant<
- std::is_copy_constructible<T>::value && __has_trivial_copy(T)> {};
- template <typename T>
- struct is_trivially_move_constructible : bool_constant<__is_trivial(T)> {};
- template <typename T>
- struct is_trivially_copy_assignable
- : bool_constant<
- std::is_copy_assignable<T>::value && __has_trivial_assign(T)> {};
- template <typename T>
- struct is_trivially_move_assignable : bool_constant<__is_trivial(T)> {};
- #endif
- template <typename T, bool>
- struct dependent_type : T {};
- template <typename Is, std::size_t J>
- struct push_back;
- template <typename Is, std::size_t J>
- using push_back_t = typename push_back<Is, J>::type;
- template <std::size_t... Is, std::size_t J>
- struct push_back<index_sequence<Is...>, J> {
- using type = index_sequence<Is..., J>;
- };
- } // namespace lib
- } // namespace mpark
- #undef MPARK_RETURN
- #endif // MPARK_LIB_HPP
|