// 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 #include #include #include #include "config.hpp" #define MPARK_RETURN(...) \ noexcept(noexcept(__VA_ARGS__)) -> decltype(__VA_ARGS__) { return __VA_ARGS__; } namespace mpark { namespace lib { template struct identity { using type = T; }; inline namespace cpp14 { template struct array { constexpr const T &operator[](std::size_t index) const { return data[index]; } T data[N == 0 ? 1 : N]; }; template using add_pointer_t = typename std::add_pointer::type; template using common_type_t = typename std::common_type::type; template using decay_t = typename std::decay::type; template using enable_if_t = typename std::enable_if::type; template using remove_const_t = typename std::remove_const::type; template using remove_reference_t = typename std::remove_reference::type; template inline constexpr T &&forward(remove_reference_t &t) noexcept { return static_cast(t); } template inline constexpr T &&forward(remove_reference_t &&t) noexcept { static_assert(!std::is_lvalue_reference::value, "can not forward an rvalue as an lvalue"); return static_cast(t); } template inline constexpr remove_reference_t &&move(T &&t) noexcept { return static_cast &&>(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 struct integer_sequence { using value_type = T; static constexpr std::size_t size() noexcept { return sizeof...(Is); } }; template using index_sequence = integer_sequence; template struct make_index_sequence_concat; template struct make_index_sequence_concat, index_sequence> : identity> {}; template struct make_index_sequence_impl; template using make_index_sequence = typename make_index_sequence_impl::type; template struct make_index_sequence_impl : make_index_sequence_concat, make_index_sequence> {}; template <> struct make_index_sequence_impl<0> : identity> {}; template <> struct make_index_sequence_impl<1> : identity> {}; template using index_sequence_for = make_index_sequence; #endif // #ifdef MPARK_TRANSPARENT_OPERATORS using equal_to = std::equal_to<>; #else struct equal_to { template inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const MPARK_RETURN(lib::forward(lhs) == lib::forward(rhs)) }; #endif #ifdef MPARK_TRANSPARENT_OPERATORS using not_equal_to = std::not_equal_to<>; #else struct not_equal_to { template inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const MPARK_RETURN(lib::forward(lhs) != lib::forward(rhs)) }; #endif #ifdef MPARK_TRANSPARENT_OPERATORS using less = std::less<>; #else struct less { template inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const MPARK_RETURN(lib::forward(lhs) < lib::forward(rhs)) }; #endif #ifdef MPARK_TRANSPARENT_OPERATORS using greater = std::greater<>; #else struct greater { template inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const MPARK_RETURN(lib::forward(lhs) > lib::forward(rhs)) }; #endif #ifdef MPARK_TRANSPARENT_OPERATORS using less_equal = std::less_equal<>; #else struct less_equal { template inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const MPARK_RETURN(lib::forward(lhs) <= lib::forward(rhs)) }; #endif #ifdef MPARK_TRANSPARENT_OPERATORS using greater_equal = std::greater_equal<>; #else struct greater_equal { template inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const MPARK_RETURN(lib::forward(lhs) >= lib::forward(rhs)) }; #endif } // namespace cpp14 inline namespace cpp17 { // template using bool_constant = std::integral_constant; template struct voider : identity {}; template using void_t = typename voider::type; namespace detail { namespace swappable { using std::swap; template struct is_swappable { private: template (), std::declval()))> inline static std::true_type test(int); template inline static std::false_type test(...); public: static constexpr bool value = decltype(test(0))::value; }; template struct is_nothrow_swappable { static constexpr bool value = noexcept(swap(std::declval(), std::declval())); }; template struct is_nothrow_swappable : std::false_type {}; } // namespace swappable } // namespace detail using detail::swappable::is_swappable; template using is_nothrow_swappable = detail::swappable::is_nothrow_swappable::value, T>; // namespace detail { template struct is_reference_wrapper : std::false_type {}; template struct is_reference_wrapper> : std::true_type {}; template struct Invoke; template <> struct Invoke { template inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&... args) MPARK_RETURN((lib::forward(arg).*pmf)(lib::forward(args)...)) }; template <> struct Invoke { template inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&... args) MPARK_RETURN((lib::forward(arg).get().*pmf)(lib::forward(args)...)) }; template <> struct Invoke { template inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&... args) MPARK_RETURN(((*lib::forward(arg)).*pmf)(lib::forward(args)...)) }; template <> struct Invoke { template inline static constexpr auto invoke(R T::*pmo, Arg &&arg) MPARK_RETURN(lib::forward(arg).*pmo) }; template <> struct Invoke { template inline static constexpr auto invoke(R T::*pmo, Arg &&arg) MPARK_RETURN(lib::forward(arg).get().*pmo) }; template <> struct Invoke { template inline static constexpr auto invoke(R T::*pmo, Arg &&arg) MPARK_RETURN((*lib::forward(arg)).*pmo) }; template inline constexpr auto invoke(R T::*f, Arg &&arg, Args &&... args) MPARK_RETURN( Invoke::value, (std::is_base_of>::value ? 0 : is_reference_wrapper>::value ? 1 : 2)>::invoke(f, lib::forward(arg), lib::forward(args)...)) #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4100) #endif template inline constexpr auto invoke(F &&f, Args &&... args) MPARK_RETURN(lib::forward(f)(lib::forward(args)...)) #ifdef _MSC_VER #pragma warning(pop) #endif } // namespace detail template inline constexpr auto invoke(F &&f, Args &&... args) MPARK_RETURN(detail::invoke(lib::forward(f), lib::forward(args)...)) namespace detail { template struct invoke_result {}; template struct invoke_result(), std::declval()...))>, F, Args...> : identity(), std::declval()...))> {}; } // namespace detail template using invoke_result = detail::invoke_result; template using invoke_result_t = typename invoke_result::type; namespace detail { template struct is_invocable : std::false_type {}; template struct is_invocable>, F, Args...> : std::true_type {}; template struct is_invocable_r : std::false_type {}; template struct is_invocable_r>, R, F, Args...> : std::is_convertible, R> {}; } // namespace detail template using is_invocable = detail::is_invocable; template using is_invocable_r = detail::is_invocable_r; namespace detail { template struct is_nothrow_invocable { static constexpr bool value = noexcept(lib::invoke(std::declval(), std::declval()...)); }; template struct is_nothrow_invocable : std::false_type {}; template struct is_nothrow_invocable_r { private: inline static R impl() { return lib::invoke(std::declval(), std::declval()...); } public: static constexpr bool value = noexcept(impl()); }; template struct is_nothrow_invocable_r : std::false_type {}; } // namespace detail template using is_nothrow_invocable = detail:: is_nothrow_invocable::value, F, Args...>; template using is_nothrow_invocable_r = detail::is_nothrow_invocable_r::value, R, F, Args...>; // #ifdef MPARK_BUILTIN_ADDRESSOF template inline constexpr T *addressof(T &arg) noexcept { return __builtin_addressof(arg); } #else namespace detail { namespace has_addressof_impl { struct fail; template inline fail operator&(T &&); template inline static constexpr bool impl() { return (std::is_class::value || std::is_union::value) && !std::is_same()), fail>::value; } } // namespace has_addressof_impl template using has_addressof = bool_constant()>; template inline constexpr T *addressof(T &arg, std::true_type) noexcept { return std::addressof(arg); } template inline constexpr T *addressof(T &arg, std::false_type) noexcept { return &arg; } } // namespace detail template inline constexpr T *addressof(T &arg) noexcept { return detail::addressof(arg, detail::has_addressof{}); } #endif template inline constexpr T *addressof(const T &&) = delete; } // namespace cpp17 template struct remove_all_extents : identity {}; template struct remove_all_extents> : remove_all_extents {}; template using remove_all_extents_t = typename remove_all_extents::type; template using size_constant = std::integral_constant; template struct indexed_type : size_constant { using type = T; }; template using all = std::is_same, integer_sequence>; #ifdef MPARK_TYPE_PACK_ELEMENT template using type_pack_element_t = __type_pack_element; #else template struct type_pack_element_impl { private: template struct set; template struct set> : indexed_type... {}; template inline static std::enable_if impl(indexed_type); inline static std::enable_if impl(...); public: using type = decltype(impl(set>{})); }; template using type_pack_element = typename type_pack_element_impl::type; template using type_pack_element_t = typename type_pack_element::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 struct is_trivially_copy_constructible : bool_constant< std::is_copy_constructible::value && __has_trivial_copy(T)> {}; template struct is_trivially_move_constructible : bool_constant<__is_trivial(T)> {}; template struct is_trivially_copy_assignable : bool_constant< std::is_copy_assignable::value && __has_trivial_assign(T)> {}; template struct is_trivially_move_assignable : bool_constant<__is_trivial(T)> {}; #endif template struct dependent_type : T {}; template struct push_back; template using push_back_t = typename push_back::type; template struct push_back, J> { using type = index_sequence; }; } // namespace lib } // namespace mpark #undef MPARK_RETURN #endif // MPARK_LIB_HPP