|
- /// \file
- // Range v3 library
- //
- // Copyright Eric Niebler 2013-present
- // Copyright Casey Carter 2016
- //
- // 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_COMPRESSED_PAIR_HPP
- #define RANGES_V3_UTILITY_COMPRESSED_PAIR_HPP
-
- #include <type_traits>
- #include <utility>
-
- #include <meta/meta.hpp>
-
- #include <concepts/concepts.hpp>
-
- #include <range/v3/range_fwd.hpp>
-
- #include <range/v3/utility/box.hpp>
- #include <range/v3/utility/static_const.hpp>
-
- namespace ranges
- {
- /// \cond
- namespace compressed_tuple_detail
- {
- // tagging individual elements with the complete type list disambiguates
- // base classes when composing compressed_tuples recursively.
- template<typename T, std::size_t I, typename... Ts>
- using storage = box<T, meta::list<meta::size_t<I>, Ts...>>;
-
- template<typename List, typename Indices>
- struct compressed_tuple_;
- template<typename... Ts, std::size_t... Is>
- struct RANGES_EMPTY_BASES
- compressed_tuple_<meta::list<Ts...>, meta::index_sequence<Is...>>
- : storage<Ts, Is, Ts...>...
- {
- static_assert(same_as<meta::index_sequence<Is...>,
- meta::make_index_sequence<sizeof...(Is)>>,
- "What madness is this?!?");
-
- compressed_tuple_() = default;
-
- template<typename... Args,
- meta::if_<meta::and_c<META_IS_CONSTRUCTIBLE(Ts, Args)...>, int> = 0>
- constexpr compressed_tuple_(Args &&... args) noexcept(
- meta::strict_and<std::is_nothrow_constructible<storage<Ts, Is, Ts...>,
- Args>...>::value)
- : storage<Ts, Is, Ts...>{static_cast<Args &&>(args)}...
- {}
-
- template<
- typename... Us,
- meta::if_<meta::and_c<META_IS_CONSTRUCTIBLE(Us, Ts const &)...>, int> = 0>
- constexpr operator std::tuple<Us...>() const noexcept(
- meta::strict_and<std::is_nothrow_constructible<Us, Ts const &>...>::value)
- {
- return std::tuple<Us...>{get<Is>(*this)...};
- }
-
- template<std::size_t I, typename T = meta::at_c<meta::list<Ts...>, I>>
- friend constexpr T & get(compressed_tuple_ & tuple) noexcept
- {
- return static_cast<storage<T, I, Ts...> &>(tuple).get();
- }
- template<std::size_t I, typename T = meta::at_c<meta::list<Ts...>, I>>
- friend constexpr T const & get(compressed_tuple_ const & tuple) noexcept
- {
- return static_cast<storage<T, I, Ts...> const &>(tuple).get();
- }
- template<std::size_t I, typename T = meta::at_c<meta::list<Ts...>, I>>
- friend constexpr T && get(compressed_tuple_ && tuple) noexcept
- {
- return static_cast<storage<T, I, Ts...> &&>(tuple).get();
- }
- template<std::size_t I, typename T = meta::at_c<meta::list<Ts...>, I>>
- friend constexpr T const && get(compressed_tuple_ const && tuple) noexcept
- {
- return static_cast<storage<T, I, Ts...> const &&>(tuple).get();
- }
- };
-
- template<typename... Ts>
- using compressed_tuple RANGES_DEPRECATED(
- "ranges::compressed_tuple is deprecated.") =
- compressed_tuple_<meta::list<Ts...>,
- meta::make_index_sequence<sizeof...(Ts)>>;
- } // namespace compressed_tuple_detail
- /// \endcond
-
- using compressed_tuple_detail::compressed_tuple;
-
- struct make_compressed_tuple_fn
- {
- // clang-format off
- template<typename... Args>
- constexpr auto CPP_auto_fun(operator())(Args &&... args) (const)
- (
- return compressed_tuple<bind_element_t<Args>...>{static_cast<Args &&>(args)...}
- )
- // clang-format on
- };
-
- /// \ingroup group-utility
- /// \sa `make_compressed_tuple_fn`
- RANGES_INLINE_VARIABLE(make_compressed_tuple_fn, make_compressed_tuple)
-
- template<typename First, typename Second>
- struct RANGES_EMPTY_BASES compressed_pair
- : box<First, meta::size_t<0>>
- , box<Second, meta::size_t<1>>
- {
- using first_type = First;
- using second_type = Second;
-
- compressed_pair() = default;
-
- CPP_template(typename U, typename V)( //
- requires constructible_from<First, U> && constructible_from<Second, V>) //
- constexpr compressed_pair(U && u,
- V && v) noexcept(noexcept(First((U &&) u)) &&
- noexcept(Second((V &&) v)))
- : box<First, meta::size_t<0>>{(U &&) u}
- , box<Second, meta::size_t<1>>{(V &&) v}
- {}
-
- constexpr First & first() &
- {
- return this->box<First, meta::size_t<0>>::get();
- }
- constexpr First const & first() const &
- {
- return this->box<First, meta::size_t<0>>::get();
- }
- constexpr First && first() &&
- {
- return static_cast<First &&>(this->box<First, meta::size_t<0>>::get());
- }
-
- constexpr Second & second() &
- {
- return this->box<Second, meta::size_t<1>>::get();
- }
- constexpr Second const & second() const &
- {
- return this->box<Second, meta::size_t<1>>::get();
- }
- constexpr Second && second() &&
- {
- return static_cast<Second &&>(this->box<Second, meta::size_t<1>>::get());
- }
-
- CPP_template(typename F, typename S)( //
- requires convertible_to<First const &, F> &&
- convertible_to<Second const &, S>) //
- constexpr
- operator std::pair<F, S>() const
- {
- return std::pair<F, S>{first(), second()};
- }
- };
-
- struct make_compressed_pair_fn
- {
- // clang-format off
- template<typename First, typename Second>
- constexpr auto CPP_auto_fun(operator())(First &&f, Second &&s) (const)
- (
- return compressed_pair<bind_element_t<First>, bind_element_t<Second>>{
- static_cast<First &&>(f), static_cast<Second &&>(s)
- }
- )
- // clang-format on
- };
-
- /// \ingroup group-utility
- /// \sa `make_compressed_pair_fn`
- RANGES_INLINE_VARIABLE(make_compressed_pair_fn, make_compressed_pair)
- } // namespace ranges
-
- RANGES_DIAGNOSTIC_PUSH
- RANGES_DIAGNOSTIC_IGNORE_MISMATCHED_TAGS
- namespace std
- {
- template<typename... Ts, size_t... Is>
- struct tuple_size<::ranges::compressed_tuple_detail::compressed_tuple_<
- ::meta::list<Ts...>, ::meta::index_sequence<Is...>>>
- : integral_constant<size_t, sizeof...(Ts)>
- {};
-
- template<size_t I, typename... Ts, size_t... Is>
- struct tuple_element<I, ::ranges::compressed_tuple_detail::compressed_tuple_<
- ::meta::list<Ts...>, ::meta::index_sequence<Is...>>>
- {
- using type = ::meta::at_c<::meta::list<Ts...>, I>;
- };
-
- template<typename First, typename Second>
- struct tuple_size<::ranges::compressed_pair<First, Second>>
- : integral_constant<size_t, 2>
- {};
-
- template<typename First, typename Second>
- struct tuple_element<0, ::ranges::compressed_pair<First, Second>>
- {
- using type = First;
- };
-
- template<typename First, typename Second>
- struct tuple_element<1, ::ranges::compressed_pair<First, Second>>
- {
- using type = Second;
- };
- } // namespace std
- RANGES_DIAGNOSTIC_POP
-
- #endif
|