|
- /// \file
- // Range v3 library
- //
- // Copyright Eric Niebler 2013-present
- //
- // Use, modification and distribution is subject to the
- // Boost Software License, Version 1.0. (See accompanying
- // file LICENSE_1_0.txt or copy at
- // http://www.boost.org/LICENSE_1_0.txt)
- //
- // Project home: https://github.com/ericniebler/range-v3
- //
-
- #ifndef RANGES_V3_UTILITY_COMMON_TUPLE_HPP
- #define RANGES_V3_UTILITY_COMMON_TUPLE_HPP
-
- #include <utility>
-
- #include <meta/meta.hpp>
-
- #include <concepts/concepts.hpp>
-
- #include <range/v3/range_fwd.hpp>
-
- #include <range/v3/detail/adl_get.hpp>
- #include <range/v3/functional/bind.hpp>
- #include <range/v3/functional/reference_wrapper.hpp>
- #include <range/v3/utility/common_type.hpp>
- #include <range/v3/utility/tuple_algorithm.hpp>
-
- namespace ranges
- {
- /// \cond
- namespace detail
- {
- template<typename... Us, typename Tup, std::size_t... Is>
- std::tuple<Us...> to_std_tuple(Tup && tup, meta::index_sequence<Is...>)
- {
- return std::tuple<Us...>{adl_get<Is>(static_cast<Tup &&>(tup))...};
- }
-
- #ifdef RANGES_WORKAROUND_MSVC_786312
- template<std::size_t, typename...>
- struct args_;
-
- template<typename, typename>
- inline constexpr bool argstructible = false;
- template<std::size_t N, typename... Ts, typename... Us>
- inline constexpr bool argstructible<args_<N, Ts...>, args_<N, Us...>> =
- (META_IS_CONSTRUCTIBLE(Ts, Us) && ...);
-
- template<typename, typename>
- inline constexpr bool argsignable = false;
- template<std::size_t N, typename... Ts, typename... Us>
- inline constexpr bool argsignable<args_<N, Ts...>, args_<N, Us...>> =
- (std::is_assignable_v<Ts &, Us> && ...);
- #endif // RANGES_WORKAROUND_MSVC_786312
-
- template<std::size_t N, typename... Ts>
- struct args_
- {
- template<typename... Us>
- args_(args_<N, Us...>, meta::if_c<
- #ifdef RANGES_WORKAROUND_MSVC_786312
- argstructible<args_, args_<N, Us...>>
- #else // ^^^ workaround / no workaround vvv
- meta::and_c<META_IS_CONSTRUCTIBLE(Ts,
- Us)...>::value
- #endif // RANGES_WORKAROUND_MSVC_786312
- > * = nullptr)
- {}
- template<typename... Us>
- meta::if_c<
- #ifdef RANGES_WORKAROUND_MSVC_786312
- argsignable<args_, args_<N, Us...>>,
- #else // ^^^ workaround / no workaround vvv
- meta::and_c<std::is_assignable<Ts &, Us>::value...>::value,
- #endif // RANGES_WORKAROUND_MSVC_786312
- args_ &>
- operator=(args_<N, Us...>)
- {
- return *this;
- }
- };
- template<typename... Ts>
- using args = args_<sizeof...(Ts), Ts...>;
- template<typename... Ts>
- using rargs = args_<sizeof...(Ts), Ts &...>;
- } // namespace detail
- /// \endcond
-
- template<typename... Ts>
- struct common_tuple : _tuple_wrapper_::forward_tuple_interface<std::tuple<Ts...>>
- {
- private:
- template<typename That, std::size_t... Is>
- common_tuple(That && that, meta::index_sequence<Is...>)
- : common_tuple::forward_tuple_interface{
- detail::adl_get<Is>(static_cast<That &&>(that))...}
- {}
- struct element_assign_
- {
- template<typename T, typename U>
- int operator()(T & t, U && u) const
- {
- t = static_cast<U &&>(u);
- return 0;
- }
- };
-
- public:
- // Construction
- CPP_member
- CPP_ctor(common_tuple)()( //
- noexcept(meta::and_c<
- std::is_nothrow_default_constructible<Ts>::value...>::value) //
- requires default_constructible<std::tuple<Ts...>>)
- : common_tuple::forward_tuple_interface{}
- {}
- CPP_template(typename... Us)( //
- requires constructible_from<detail::args<Ts...>, detail::args<Us...>>) //
- explicit common_tuple(Us &&... us) noexcept(
- meta::and_c<std::is_nothrow_constructible<Ts, Us>::value...>::value)
- : common_tuple::forward_tuple_interface{static_cast<Us &&>(us)...}
- {}
- template<typename... Us>
- CPP_ctor(common_tuple)(std::tuple<Us...> & that)( //
- noexcept(
- meta::and_c<std::is_nothrow_constructible<Ts, Us &>::value...>::value) //
- requires constructible_from<detail::args<Ts...>, detail::rargs<Us...>>)
- : common_tuple(that, meta::make_index_sequence<sizeof...(Ts)>{})
- {}
- template<typename... Us>
- CPP_ctor(common_tuple)(std::tuple<Us...> const & that)( //
- noexcept(meta::and_c<
- std::is_nothrow_constructible<Ts, Us const &>::value...>::value) //
- requires constructible_from<detail::args<Ts...>, detail::rargs<Us const...>>)
- : common_tuple(that, meta::make_index_sequence<sizeof...(Ts)>{})
- {}
- template<typename... Us>
- CPP_ctor(common_tuple)(std::tuple<Us...> && that)( //
- noexcept(
- meta::and_c<std::is_nothrow_constructible<Ts, Us>::value...>::value) //
- requires constructible_from<detail::args<Ts...>, detail::args<Us...>>)
- : common_tuple(std::move(that), meta::make_index_sequence<sizeof...(Ts)>{})
- {}
- template<typename... Us>
- CPP_ctor(common_tuple)(common_tuple<Us...> & that)( //
- noexcept(
- meta::and_c<std::is_nothrow_constructible<Ts, Us &>::value...>::value) //
- requires constructible_from<detail::args<Ts...>, detail::rargs<Us...>>)
- : common_tuple(that, meta::make_index_sequence<sizeof...(Ts)>{})
- {}
- template<typename... Us>
- CPP_ctor(common_tuple)(common_tuple<Us...> const & that)( //
- noexcept(meta::and_c<
- std::is_nothrow_constructible<Ts, Us const &>::value...>::value) //
- requires constructible_from<detail::args<Ts...>, detail::rargs<Us const...>>)
- : common_tuple(that, meta::make_index_sequence<sizeof...(Ts)>{})
- {}
- template<typename... Us>
- CPP_ctor(common_tuple)(common_tuple<Us...> && that)( //
- noexcept(
- meta::and_c<std::is_nothrow_constructible<Ts, Us>::value...>::value) //
- requires constructible_from<detail::args<Ts...>, detail::args<Us...>>)
- : common_tuple(std::move(that), meta::make_index_sequence<sizeof...(Ts)>{})
- {}
-
- std::tuple<Ts...> & base() noexcept
- {
- return *this;
- }
- std::tuple<Ts...> const & base() const noexcept
- {
- return *this;
- }
-
- // Assignment
- template<typename... Us>
- auto operator=(std::tuple<Us...> & that) noexcept(
- meta::and_c<std::is_nothrow_assignable<Ts &, Us &>::value...>::value)
- -> CPP_ret(common_tuple &)( //
- requires assignable_from<detail::args<Ts...> &, detail::rargs<Us...>>)
- {
- (void)tuple_transform(base(), that, element_assign_{});
- return *this;
- }
- template<typename... Us>
- auto operator=(std::tuple<Us...> const & that) noexcept(
- meta::and_c<std::is_nothrow_assignable<Ts &, Us const &>::value...>::value)
- -> CPP_ret(common_tuple &)( //
- requires assignable_from<detail::args<Ts...> &,
- detail::rargs<Us const...>>)
- {
- (void)tuple_transform(base(), that, element_assign_{});
- return *this;
- }
- template<typename... Us>
- auto operator=(std::tuple<Us...> && that) noexcept(
- meta::and_c<std::is_nothrow_assignable<Ts &, Us>::value...>::value)
- -> CPP_ret(common_tuple &)( //
- requires assignable_from<detail::args<Ts...> &, detail::args<Us...>>)
- {
- (void)tuple_transform(base(), std::move(that), element_assign_{});
- return *this;
- }
-
- template<typename... Us>
- auto operator=(std::tuple<Us...> & that) const noexcept(
- meta::and_c<std::is_nothrow_assignable<Ts const &, Us &>::value...>::value)
- -> CPP_ret(common_tuple const &)( //
- requires assignable_from<detail::args<Ts const...> &,
- detail::rargs<Us...>>)
- {
- (void)tuple_transform(base(), that, element_assign_{});
- return *this;
- }
- template<typename... Us>
- auto operator=(std::tuple<Us...> const & that) const
- noexcept(meta::and_c<
- std::is_nothrow_assignable<Ts const &, Us const &>::value...>::value)
- -> CPP_ret(common_tuple const &)( //
- requires assignable_from<detail::args<Ts const...> &,
- detail::rargs<Us const...>>)
- {
- (void)tuple_transform(base(), that, element_assign_{});
- return *this;
- }
- template<typename... Us>
- auto operator=(std::tuple<Us...> && that) const noexcept(
- meta::and_c<std::is_nothrow_assignable<Ts const &, Us &&>::value...>::value)
- -> CPP_ret(common_tuple const &)( //
- requires assignable_from<detail::args<Ts const...> &,
- detail::args<Us...>>)
- {
- (void)tuple_transform(base(), std::move(that), element_assign_{});
- return *this;
- }
-
- // Conversion
- CPP_template(typename... Us)( //
- requires constructible_from<detail::args<Us...>, detail::rargs<Ts...>>) //
- operator std::tuple<Us...>() &
- noexcept(
- meta::and_c<std::is_nothrow_constructible<Us, Ts &>::value...>::value)
- {
- return detail::to_std_tuple<Us...>(
- *this, meta::make_index_sequence<sizeof...(Ts)>{});
- }
- CPP_template(typename... Us)( //
- requires constructible_from<detail::args<Us...>,
- detail::rargs<Ts const...>>) //
- operator std::tuple<Us...>() const & noexcept(
- meta::and_c<std::is_nothrow_constructible<Us, Ts const &>::value...>::value)
- {
- return detail::to_std_tuple<Us...>(
- *this, meta::make_index_sequence<sizeof...(Ts)>{});
- }
- CPP_template(typename... Us)( //
- requires constructible_from<detail::args<Us...>, detail::args<Ts...>>) //
- operator std::tuple<Us...>() &&
- noexcept(meta::and_c<std::is_nothrow_constructible<Us, Ts>::value...>::value)
- {
- return detail::to_std_tuple<Us...>(
- std::move(*this), meta::make_index_sequence<sizeof...(Ts)>{});
- }
- };
-
- // Logical operators
- #define LOGICAL_OP(OP, CONCEPT) \
- template<typename... Ts, typename... Us> \
- auto operator OP(common_tuple<Ts...> const & a, common_tuple<Us...> const & b) \
- ->CPP_ret(bool)(requires and_v<CONCEPT<Ts, Us>...>) \
- { \
- return a.base() OP b.base(); \
- } \
- template<typename... Ts, typename... Us> \
- auto operator OP(std::tuple<Ts...> const & a, common_tuple<Us...> const & b) \
- ->CPP_ret(bool)(requires and_v<CONCEPT<Ts, Us>...>) \
- { \
- return a OP b.base(); \
- } \
- template<typename... Ts, typename... Us> \
- auto operator OP(common_tuple<Ts...> const & a, std::tuple<Us...> const & b) \
- ->CPP_ret(bool)(requires and_v<CONCEPT<Ts, Us>...>) \
- { \
- return a.base() OP b; \
- } \
- /**/
- LOGICAL_OP(==, equality_comparable_with)
- LOGICAL_OP(!=, equality_comparable_with)
- LOGICAL_OP(<, totally_ordered_with)
- LOGICAL_OP(<=, totally_ordered_with)
- LOGICAL_OP(>, totally_ordered_with)
- LOGICAL_OP(>=, totally_ordered_with)
- #undef LOGICAL_OP
-
- struct make_common_tuple_fn
- {
- template<typename... Args>
- common_tuple<bind_element_t<Args>...> operator()(Args &&... args) const noexcept(
- meta::and_c<std::is_nothrow_constructible<
- bind_element_t<Args>, unwrap_reference_t<Args>>::value...>::value)
- {
- return common_tuple<bind_element_t<Args>...>{
- unwrap_reference(static_cast<Args &&>(args))...};
- }
- };
-
- /// \ingroup group-utility
- /// \sa `make_common_tuple_fn`
- RANGES_INLINE_VARIABLE(make_common_tuple_fn, make_common_tuple)
-
- template<typename F, typename S>
- struct common_pair : std::pair<F, S>
- {
- private:
- std::pair<F, S> const & base() const noexcept
- {
- return *this;
- }
-
- public:
- // Construction
- CPP_member
- CPP_ctor(common_pair)()( //
- noexcept(std::is_nothrow_default_constructible<F>::value &&
- std::is_nothrow_default_constructible<S>::value) //
- requires default_constructible<F> && default_constructible<S>)
- : std::pair<F, S>{}
- {}
- template<typename F2, typename S2>
- CPP_ctor(common_pair)(F2 && f2, S2 && s2)( //
- noexcept(std::is_nothrow_constructible<F, F2>::value &&
- std::is_nothrow_constructible<S, S2>::value) //
- requires constructible_from<F, F2> && constructible_from<S, S2>)
- : std::pair<F, S>{static_cast<F2 &&>(f2), static_cast<S2 &&>(s2)}
- {}
- template<typename F2, typename S2>
- CPP_ctor(common_pair)(std::pair<F2, S2> & that)( //
- noexcept(std::is_nothrow_constructible<F, F2 &>::value &&
- std::is_nothrow_constructible<S, S2 &>::value) //
- requires constructible_from<F, F2 &> && constructible_from<S, S2 &>)
- : std::pair<F, S>{that.first, that.second}
- {}
- template<typename F2, typename S2>
- CPP_ctor(common_pair)(std::pair<F2, S2> const & that)( //
- noexcept(std::is_nothrow_constructible<F, F2 const &>::value &&
- std::is_nothrow_constructible<S, S2 const &>::value) //
- requires constructible_from<F, F2 const &> &&
- constructible_from<S, S2 const &>)
- : std::pair<F, S>{that.first, that.second}
- {}
- template<typename F2, typename S2>
- CPP_ctor(common_pair)(std::pair<F2, S2> && that)( //
- noexcept(std::is_nothrow_constructible<F, F2>::value &&
- std::is_nothrow_constructible<S, S2>::value) //
- requires constructible_from<F, F2> && constructible_from<S, S2>)
- : std::pair<F, S>{std::forward<F2>(that.first), std::forward<S2>(that.second)}
- {}
-
- // Conversion
- CPP_template(typename F2, typename S2)( //
- requires constructible_from<F2, F &> && constructible_from<S2, S &>) //
- operator std::pair<F2, S2>() &
- noexcept(std::is_nothrow_constructible<F2, F &>::value &&
- std::is_nothrow_constructible<S2, S &>::value)
- {
- return {this->first, this->second};
- }
- CPP_template(typename F2, typename S2)( //
- requires constructible_from<F2, F const &> &&
- constructible_from<S2, S const &>) //
- operator std::pair<F2, S2>() const & noexcept(
- std::is_nothrow_constructible<F2, F const &>::value &&
- std::is_nothrow_constructible<S2, S const &>::value)
- {
- return {this->first, this->second};
- }
- CPP_template(typename F2, typename S2)( //
- requires constructible_from<F2, F> && constructible_from<S2, S>) //
- operator std::pair<F2, S2>() &&
- noexcept(std::is_nothrow_constructible<F2, F>::value &&
- std::is_nothrow_constructible<S2, S>::value)
- {
- return {std::forward<F>(this->first), std::forward<S>(this->second)};
- }
-
- // Assignment
- template<typename F2, typename S2>
- auto operator=(std::pair<F2, S2> & that) noexcept(
- std::is_nothrow_assignable<F &, F2 &>::value &&
- std::is_nothrow_assignable<S &, S2 &>::value)
- -> CPP_ret(common_pair &)( //
- requires assignable_from<F &, F2 &> && assignable_from<S &, S2 &>)
- {
- this->first = that.first;
- this->second = that.second;
- return *this;
- }
- template<typename F2, typename S2>
- auto operator=(std::pair<F2, S2> const & that) noexcept(
- std::is_nothrow_assignable<F &, F2 const &>::value &&
- std::is_nothrow_assignable<S &, S2 const &>::value)
- -> CPP_ret(common_pair &)( //
- requires assignable_from<F &, F2 const &> &&
- assignable_from<S &, S2 const &>)
- {
- this->first = that.first;
- this->second = that.second;
- return *this;
- }
- template<typename F2, typename S2>
- auto operator=(std::pair<F2, S2> && that) noexcept(
- std::is_nothrow_assignable<F &, F2>::value &&
- std::is_nothrow_assignable<S &, S2>::value) -> CPP_ret(common_pair &)( //
- requires assignable_from<F &, F2> && assignable_from<S &, S2>)
- {
- this->first = static_cast<F2 &&>(that.first);
- this->second = static_cast<S2 &&>(that.second);
- return *this;
- }
-
- template<typename F2, typename S2>
- auto operator=(std::pair<F2, S2> & that) const
- noexcept(std::is_nothrow_assignable<F const &, F2 &>::value &&
- std::is_nothrow_assignable<S const &, S2 &>::value)
- -> CPP_ret(common_pair const &)( //
- requires assignable_from<F const &, F2 &> &&
- assignable_from<S const &, S2 &>)
- {
- this->first = that.first;
- this->second = that.second;
- return *this;
- }
- template<typename F2, typename S2>
- auto operator=(std::pair<F2, S2> const & that) const
- noexcept(std::is_nothrow_assignable<F const &, F2 const &>::value &&
- std::is_nothrow_assignable<S const &, S2 const &>::value)
- -> CPP_ret(common_pair const &)( //
- requires assignable_from<F const &, F2 const &> &&
- assignable_from<S const &, S2 const &>)
- {
- this->first = that.first;
- this->second = that.second;
- return *this;
- }
- template<typename F2, typename S2>
- auto operator=(std::pair<F2, S2> && that) const noexcept(
- std::is_nothrow_assignable<F const &, F2 &&>::value &&
- std::is_nothrow_assignable<S const &, S2 &&>::value)
- -> CPP_ret(common_pair const &)( //
- requires assignable_from<F const &, F2> && assignable_from<S const &, S2>)
- {
- this->first = static_cast<F2 &&>(that.first);
- this->second = static_cast<S2 &&>(that.second);
- return *this;
- }
- };
-
- // Logical operators
- template<typename F1, typename S1, typename F2, typename S2>
- auto operator==(common_pair<F1, S1> const & a, common_pair<F2, S2> const & b)
- -> CPP_ret(bool)( //
- requires equality_comparable_with<F1, F2> && equality_comparable_with<S1, S2>)
- {
- return a.first == b.first && a.second == b.second;
- }
- template<typename F1, typename S1, typename F2, typename S2>
- auto operator==(common_pair<F1, S1> const & a, std::pair<F2, S2> const & b)
- -> CPP_ret(bool)( //
- requires equality_comparable_with<F1, F2> && equality_comparable_with<S1, S2>)
- {
- return a.first == b.first && a.second == b.second;
- }
- template<typename F1, typename S1, typename F2, typename S2>
- auto operator==(std::pair<F1, S1> const & a, common_pair<F2, S2> const & b)
- -> CPP_ret(bool)( //
- requires equality_comparable_with<F1, F2> && equality_comparable_with<S1, S2>)
- {
- return a.first == b.first && a.second == b.second;
- }
- template<typename F1, typename S1, typename F2, typename S2>
- auto operator<(common_pair<F1, S1> const & a, common_pair<F2, S2> const & b)
- -> CPP_ret(bool)( //
- requires totally_ordered_with<F1, F2> && totally_ordered_with<S1, S2>)
- {
- return a.first < b.first || (!(b.first < a.first) && a.second < b.second);
- }
- template<typename F1, typename S1, typename F2, typename S2>
- auto operator<(std::pair<F1, S1> const & a, common_pair<F2, S2> const & b)
- -> CPP_ret(bool)( //
- requires totally_ordered_with<F1, F2> && totally_ordered_with<S1, S2>)
- {
- return a.first < b.first || (!(b.first < a.first) && a.second < b.second);
- }
- template<typename F1, typename S1, typename F2, typename S2>
- auto operator<(common_pair<F1, S1> const & a, std::pair<F2, S2> const & b)
- -> CPP_ret(bool)( //
- requires totally_ordered_with<F1, F2> && totally_ordered_with<S1, S2>)
- {
- return a.first < b.first || (!(b.first < a.first) && a.second < b.second);
- }
- #define LOGICAL_OP(OP, CONCEPT, RET) \
- template<typename F1, typename S1, typename F2, typename S2> \
- auto operator OP(common_pair<F1, S1> const & a, common_pair<F2, S2> const & b) \
- ->CPP_ret(bool)(requires CONCEPT<F1, F2> && CONCEPT<S1, S2>) \
- { \
- return RET; \
- } \
- template<typename F1, typename S1, typename F2, typename S2> \
- auto operator OP(std::pair<F1, S1> const & a, common_pair<F2, S2> const & b) \
- ->CPP_ret(bool)(requires CONCEPT<F1, F2> && CONCEPT<S1, S2>) \
- { \
- return RET; \
- } \
- template<typename F1, typename S1, typename F2, typename S2> \
- auto operator OP(common_pair<F1, S1> const & a, std::pair<F2, S2> const & b) \
- ->CPP_ret(bool)(requires CONCEPT<F1, F2> && CONCEPT<S1, S2>) \
- { \
- return RET; \
- } \
- /**/
- LOGICAL_OP(!=, equality_comparable_with, !(a == b))
- LOGICAL_OP(<=, totally_ordered_with, !(b < a))
- LOGICAL_OP(>, totally_ordered_with, (b < a))
- LOGICAL_OP(>=, totally_ordered_with, !(a < b))
- #undef LOGICAL_OP
-
- struct make_common_pair_fn
- {
- template<typename First, typename Second, typename F = bind_element_t<First>,
- typename S = bind_element_t<Second>>
- common_pair<F, S> operator()(First && f, Second && s) const noexcept(
- std::is_nothrow_constructible<F, unwrap_reference_t<First>>::value &&
- std::is_nothrow_constructible<F, unwrap_reference_t<Second>>::value)
- {
- return {unwrap_reference(static_cast<First &&>(f)),
- unwrap_reference(static_cast<Second &&>(s))};
- }
- };
-
- /// \ingroup group-utility
- /// \sa `make_common_pair_fn`
- RANGES_INLINE_VARIABLE(make_common_pair_fn, make_common_pair)
-
- /// \cond
- namespace detail
- {
- template<typename, typename, typename, typename = void>
- struct common_type_tuple_like
- {};
-
- template<template<typename...> class T0, typename... Ts,
- template<typename...> class T1, typename... Us, typename TupleLike>
- struct common_type_tuple_like<T0<Ts...>, T1<Us...>, TupleLike,
- meta::if_c<sizeof...(Ts) == sizeof...(Us)>>
- : meta::lazy::let<
- meta::lazy::invoke<TupleLike, meta::lazy::_t<common_type<Ts, Us>>...>>
- {};
-
- template<typename T, typename U>
- using make_common_pair =
- meta::if_<meta::or_<std::is_reference<T>, std::is_reference<U>>,
- common_pair<T, U>, std::pair<T, U>>;
-
- template<typename... Ts>
- using make_common_tuple =
- meta::if_<meta::any_of<meta::list<Ts...>, meta::quote<std::is_reference>>,
- common_tuple<Ts...>, std::tuple<Ts...>>;
-
- template<typename, typename, typename, typename = void>
- struct common_ref_tuple_like
- {};
-
- template<template<typename...> class T0, typename... Ts,
- template<typename...> class T1, typename... Us, typename TupleLike>
- struct common_ref_tuple_like<T0<Ts...>, T1<Us...>, TupleLike,
- meta::if_c<sizeof...(Ts) == sizeof...(Us)>>
- : meta::lazy::let<meta::lazy::invoke<
- TupleLike, meta::lazy::_t<common_reference<Ts, Us>>...>>
- {};
- } // namespace detail
- /// \endcond
- } // namespace ranges
-
- /// \cond
- namespace concepts
- {
- // common_type for pairs
- template<typename F1, typename S1, typename F2, typename S2>
- struct common_type<std::pair<F1, S1>, ranges::common_pair<F2, S2>>
- : ranges::detail::common_type_tuple_like<
- std::pair<F1, S1>, ranges::common_pair<F2, S2>,
- meta::quote<ranges::detail::make_common_pair>>
- {};
- template<typename F1, typename S1, typename F2, typename S2>
- struct common_type<ranges::common_pair<F1, S1>, std::pair<F2, S2>>
- : ranges::detail::common_type_tuple_like<
- ranges::common_pair<F1, S1>, std::pair<F2, S2>,
- meta::quote<ranges::detail::make_common_pair>>
- {};
- template<typename F1, typename S1, typename F2, typename S2>
- struct common_type<ranges::common_pair<F1, S1>, ranges::common_pair<F2, S2>>
- : ranges::detail::common_type_tuple_like<ranges::common_pair<F1, S1>,
- ranges::common_pair<F2, S2>,
- meta::quote<ranges::common_pair>>
- {};
- // common_type for tuples
- template<typename... Ts, typename... Us>
- struct common_type<ranges::common_tuple<Ts...>, std::tuple<Us...>>
- : ranges::detail::common_type_tuple_like<
- ranges::common_tuple<Ts...>, std::tuple<Us...>,
- meta::quote<ranges::detail::make_common_tuple>>
- {};
- template<typename... Ts, typename... Us>
- struct common_type<std::tuple<Ts...>, ranges::common_tuple<Us...>>
- : ranges::detail::common_type_tuple_like<
- std::tuple<Ts...>, ranges::common_tuple<Us...>,
- meta::quote<ranges::detail::make_common_tuple>>
- {};
- template<typename... Ts, typename... Us>
- struct common_type<ranges::common_tuple<Ts...>, ranges::common_tuple<Us...>>
- : ranges::detail::common_type_tuple_like<ranges::common_tuple<Ts...>,
- ranges::common_tuple<Us...>,
- meta::quote<ranges::common_tuple>>
- {};
-
- // common reference for pairs
- template<typename F1, typename S1, typename F2, typename S2,
- template<typename> class Qual1, template<typename> class Qual2>
- struct basic_common_reference<ranges::common_pair<F1, S1>, std::pair<F2, S2>, Qual1,
- Qual2>
- : ranges::detail::common_ref_tuple_like<
- ranges::common_pair<Qual1<F1>, Qual1<S1>>, std::pair<Qual2<F2>, Qual2<S2>>,
- meta::quote<ranges::detail::make_common_pair>>
- {};
- template<typename F1, typename S1, typename F2, typename S2,
- template<typename> class Qual1, template<typename> class Qual2>
- struct basic_common_reference<std::pair<F1, S1>, ranges::common_pair<F2, S2>, Qual1,
- Qual2>
- : ranges::detail::common_ref_tuple_like<
- std::pair<Qual1<F1>, Qual1<S1>>, ranges::common_pair<Qual2<F2>, Qual2<S2>>,
- meta::quote<ranges::detail::make_common_pair>>
- {};
- template<typename F1, typename S1, typename F2, typename S2,
- template<typename> class Qual1, template<typename> class Qual2>
- struct basic_common_reference<ranges::common_pair<F1, S1>,
- ranges::common_pair<F2, S2>, Qual1, Qual2>
- : ranges::detail::common_ref_tuple_like<ranges::common_pair<Qual1<F1>, Qual1<S1>>,
- ranges::common_pair<Qual2<F2>, Qual2<S2>>,
- meta::quote<ranges::common_pair>>
- {};
- // common reference for tuples
- template<typename... Ts, typename... Us, template<typename> class Qual1,
- template<typename> class Qual2>
- struct basic_common_reference<ranges::common_tuple<Ts...>, std::tuple<Us...>, Qual1,
- Qual2>
- : ranges::detail::common_ref_tuple_like<
- ranges::common_tuple<Qual1<Ts>...>, std::tuple<Qual2<Us>...>,
- meta::quote<ranges::detail::make_common_tuple>>
- {};
- template<typename... Ts, typename... Us, template<typename> class Qual1,
- template<typename> class Qual2>
- struct basic_common_reference<std::tuple<Ts...>, ranges::common_tuple<Us...>, Qual1,
- Qual2>
- : ranges::detail::common_ref_tuple_like<
- std::tuple<Qual1<Ts>...>, ranges::common_tuple<Qual2<Us>...>,
- meta::quote<ranges::detail::make_common_tuple>>
- {};
- template<typename... Ts, typename... Us, template<typename> class Qual1,
- template<typename> class Qual2>
- struct basic_common_reference<ranges::common_tuple<Ts...>,
- ranges::common_tuple<Us...>, Qual1, Qual2>
- : ranges::detail::common_ref_tuple_like<ranges::common_tuple<Qual1<Ts>...>,
- ranges::common_tuple<Qual2<Us>...>,
- meta::quote<ranges::common_tuple>>
- {};
- } // namespace concepts
- /// \endcond
-
- RANGES_DIAGNOSTIC_PUSH
- RANGES_DIAGNOSTIC_IGNORE_MISMATCHED_TAGS
-
- namespace std
- {
- template<typename First, typename Second>
- struct tuple_size<::ranges::common_pair<First, Second>>
- : std::integral_constant<size_t, 2>
- {};
-
- template<typename First, typename Second>
- struct tuple_element<0, ::ranges::common_pair<First, Second>>
- {
- using type = First;
- };
-
- template<typename First, typename Second>
- struct tuple_element<1, ::ranges::common_pair<First, Second>>
- {
- using type = Second;
- };
-
- template<typename... Ts>
- struct tuple_size<::ranges::common_tuple<Ts...>>
- : std::integral_constant<size_t, sizeof...(Ts)>
- {};
-
- template<size_t N, typename... Ts>
- struct tuple_element<N, ::ranges::common_tuple<Ts...>>
- : tuple_element<N, tuple<Ts...>>
- {};
- } // namespace std
-
- RANGES_DIAGNOSTIC_POP
-
- #endif
|