Skip to content

[libc++] Refactor __tuple_like and __pair_like #85206

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion libcxx/include/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -709,12 +709,12 @@ set(files
__tree
__tuple/find_index.h
__tuple/make_tuple_types.h
__tuple/pair_like.h
__tuple/sfinae_helpers.h
__tuple/tuple_element.h
__tuple/tuple_indices.h
__tuple/tuple_like.h
__tuple/tuple_like_ext.h
__tuple/tuple_like_no_subrange.h
__tuple/tuple_size.h
__tuple/tuple_types.h
__type_traits/add_const.h
Expand Down
2 changes: 2 additions & 0 deletions libcxx/include/__algorithm/mismatch.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,12 @@
#include <__type_traits/invoke.h>
#include <__type_traits/is_constant_evaluated.h>
#include <__type_traits/is_equality_comparable.h>
#include <__type_traits/is_integral.h>
#include <__type_traits/operation_traits.h>
#include <__utility/move.h>
#include <__utility/pair.h>
#include <__utility/unreachable.h>
#include <cstddef>

#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
Expand Down
12 changes: 3 additions & 9 deletions libcxx/include/__memory/uses_allocator_construction.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
#include <__config>
#include <__memory/construct_at.h>
#include <__memory/uses_allocator.h>
#include <__tuple/pair_like.h>
#include <__tuple/tuple_like_no_subrange.h>
#include <__type_traits/enable_if.h>
#include <__type_traits/is_same.h>
#include <__type_traits/remove_cv.h>
Expand Down Expand Up @@ -128,11 +128,7 @@ __uses_allocator_construction_args(const _Alloc& __alloc, const pair<_Up, _Vp>&&
std::forward_as_tuple(std::get<1>(std::move(__pair))));
}

template < class _Pair,
class _Alloc,
__pair_like _PairLike,
__enable_if_t<__is_cv_std_pair<_Pair> && !__is_specialization_of_subrange<remove_cvref_t<_PairLike>>::value,
int> = 0>
template <class _Pair, class _Alloc, __pair_like_no_subrange _PairLike, __enable_if_t<__is_cv_std_pair<_Pair>, int> = 0>
_LIBCPP_HIDE_FROM_ABI constexpr auto
__uses_allocator_construction_args(const _Alloc& __alloc, _PairLike&& __p) noexcept {
return std::__uses_allocator_construction_args<_Pair>(
Expand Down Expand Up @@ -161,9 +157,7 @@ inline constexpr bool __convertible_to_const_pair_ref =
# if _LIBCPP_STD_VER >= 23
template <class _Tp, class _Up>
inline constexpr bool __uses_allocator_constraints =
__is_cv_std_pair<_Tp> &&
(__is_specialization_of_subrange<remove_cvref_t<_Up>>::value ||
(!__pair_like<_Up> && !__convertible_to_const_pair_ref<_Up>));
__is_cv_std_pair<_Tp> && !__pair_like_no_subrange<_Up> && !__convertible_to_const_pair_ref<_Up>;
# else
template <class _Tp, class _Up>
inline constexpr bool __uses_allocator_constraints = __is_cv_std_pair<_Tp> && !__convertible_to_const_pair_ref<_Up>;
Expand Down
1 change: 1 addition & 0 deletions libcxx/include/__memory_resource/polymorphic_allocator.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <__assert>
#include <__availability>
#include <__config>
#include <__fwd/pair.h>
#include <__memory_resource/memory_resource.h>
#include <__utility/exception_guard.h>
#include <cstddef>
Expand Down
7 changes: 3 additions & 4 deletions libcxx/include/__ranges/subrange.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@
#include <__ranges/enable_borrowed_range.h>
#include <__ranges/size.h>
#include <__ranges/view_interface.h>
#include <__tuple/pair_like.h>
#include <__tuple/tuple_element.h>
#include <__tuple/tuple_like_no_subrange.h>
#include <__tuple/tuple_size.h>
#include <__type_traits/conditional.h>
#include <__type_traits/decay.h>
Expand Down Expand Up @@ -64,7 +64,7 @@ concept __convertible_to_non_slicing =

template <class _Pair, class _Iter, class _Sent>
concept __pair_like_convertible_from =
!range<_Pair> && __pair_like<_Pair> && constructible_from<_Pair, _Iter, _Sent> &&
!range<_Pair> && __pair_like_no_subrange<_Pair> && constructible_from<_Pair, _Iter, _Sent> &&
__convertible_to_non_slicing<_Iter, tuple_element_t<0, _Pair>> && convertible_to<_Sent, tuple_element_t<1, _Pair>>;

template <input_or_output_iterator _Iter,
Expand Down Expand Up @@ -125,8 +125,7 @@ class _LIBCPP_TEMPLATE_VIS subrange : public view_interface<subrange<_Iter, _Sen
requires(_Kind == subrange_kind::sized)
: subrange(ranges::begin(__range), ranges::end(__range), __n) {}

template <__different_from<subrange> _Pair>
requires __pair_like_convertible_from<_Pair, const _Iter&, const _Sent&>
template <__pair_like_convertible_from<const _Iter&, const _Sent&> _Pair>
_LIBCPP_HIDE_FROM_ABI constexpr operator _Pair() const {
return _Pair(__begin_, __end_);
}
Expand Down
32 changes: 0 additions & 32 deletions libcxx/include/__tuple/pair_like.h

This file was deleted.

32 changes: 8 additions & 24 deletions libcxx/include/__tuple/tuple_like.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,9 @@
#define _LIBCPP___TUPLE_TUPLE_LIKE_H

#include <__config>
#include <__fwd/array.h>
#include <__fwd/complex.h>
#include <__fwd/pair.h>
#include <__fwd/subrange.h>
#include <__fwd/tuple.h>
#include <__type_traits/integral_constant.h>
#include <__tuple/tuple_like_no_subrange.h>
#include <__tuple/tuple_size.h>
#include <__type_traits/remove_cvref.h>

#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
Expand All @@ -27,29 +24,16 @@ _LIBCPP_BEGIN_NAMESPACE_STD
#if _LIBCPP_STD_VER >= 20

template <class _Tp>
struct __tuple_like_impl : false_type {};
inline constexpr bool __is_ranges_subrange_v = false;

template <class... _Tp>
struct __tuple_like_impl<tuple<_Tp...> > : true_type {};

template <class _T1, class _T2>
struct __tuple_like_impl<pair<_T1, _T2> > : true_type {};

template <class _Tp, size_t _Size>
struct __tuple_like_impl<array<_Tp, _Size> > : true_type {};

template <class _Ip, class _Sp, ranges::subrange_kind _Kp>
struct __tuple_like_impl<ranges::subrange<_Ip, _Sp, _Kp> > : true_type {};

# if _LIBCPP_STD_VER >= 26
template <class _Iter, class _Sent, ranges::subrange_kind _Kind>
inline constexpr bool __is_ranges_subrange_v<ranges::subrange<_Iter, _Sent, _Kind>> = true;

template <class _Tp>
struct __tuple_like_impl<complex<_Tp>> : true_type {};

# endif
concept __tuple_like = __tuple_like_no_subrange<_Tp> || __is_ranges_subrange_v<remove_cvref_t<_Tp>>;

template <class _Tp>
concept __tuple_like = __tuple_like_impl<remove_cvref_t<_Tp>>::value;
// As of writing this comment every use of `pair-like` in the standard excludes `ranges::subrange`, so
// you most likely want to use `__pair_like_no_subrange` if you're looking for `pair-like`.

#endif // _LIBCPP_STD_VER >= 20

Expand Down
61 changes: 61 additions & 0 deletions libcxx/include/__tuple/tuple_like_no_subrange.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef _LIBCPP___TUPLE_TUPLE_LIKE_NO_SUBRANGE_H
#define _LIBCPP___TUPLE_TUPLE_LIKE_NO_SUBRANGE_H

#include <__config>
#include <__fwd/array.h>
#include <__fwd/complex.h>
#include <__fwd/pair.h>
#include <__fwd/tuple.h>
#include <__tuple/tuple_size.h>
#include <__type_traits/remove_cvref.h>
#include <cstddef>

#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif

_LIBCPP_BEGIN_NAMESPACE_STD

#if _LIBCPP_STD_VER >= 20

template <class _Tp>
inline constexpr bool __tuple_like_no_subrange_impl = false;

template <class... _Tp>
inline constexpr bool __tuple_like_no_subrange_impl<tuple<_Tp...>> = true;

template <class _T1, class _T2>
inline constexpr bool __tuple_like_no_subrange_impl<pair<_T1, _T2>> = true;

template <class _Tp, size_t _Size>
inline constexpr bool __tuple_like_no_subrange_impl<array<_Tp, _Size>> = true;

# if _LIBCPP_STD_VER >= 26

template <class _Tp>
inline constexpr bool __tuple_like_no_subrange_impl<complex<_Tp>> = true;

# endif

template <class _Tp>
concept __tuple_like_no_subrange = __tuple_like_no_subrange_impl<remove_cvref_t<_Tp>>;

// This is equivalent to the exposition-only type trait `pair-like`, except that it is false for specializations of
// `ranges::subrange`. This is more useful than the pair-like concept in the standard because every use of `pair-like`
// excludes `ranges::subrange`.
template <class _Tp>
concept __pair_like_no_subrange = __tuple_like_no_subrange<_Tp> && tuple_size<remove_cvref_t<_Tp>>::value == 2;

#endif // _LIBCPP_STD_VER >= 20

_LIBCPP_END_NAMESPACE_STD

#endif // _LIBCPP___TUPLE_TUPLE_LIKE_NO_SUBRANGE_H
27 changes: 9 additions & 18 deletions libcxx/include/__utility/pair.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,11 @@
#include <__config>
#include <__fwd/array.h>
#include <__fwd/pair.h>
#include <__fwd/subrange.h>
#include <__fwd/tuple.h>
#include <__tuple/pair_like.h>
#include <__tuple/sfinae_helpers.h>
#include <__tuple/tuple_element.h>
#include <__tuple/tuple_indices.h>
#include <__tuple/tuple_like_no_subrange.h>
#include <__tuple/tuple_size.h>
#include <__type_traits/common_reference.h>
#include <__type_traits/common_type.h>
Expand Down Expand Up @@ -60,14 +59,6 @@ struct __non_trivially_copyable_base {
__non_trivially_copyable_base(__non_trivially_copyable_base const&) _NOEXCEPT {}
};

#if _LIBCPP_STD_VER >= 23
template <class _Tp>
struct __is_specialization_of_subrange : false_type {};

template <class _Iter, class _Sent, ranges::subrange_kind _Kind>
struct __is_specialization_of_subrange<ranges::subrange<_Iter, _Sent, _Kind>> : true_type {};
#endif

template <class _T1, class _T2>
struct _LIBCPP_TEMPLATE_VIS pair
#if defined(_LIBCPP_DEPRECATED_ABI_DISABLE_PAIR_TRIVIAL_COPY_CTOR)
Expand Down Expand Up @@ -201,19 +192,19 @@ struct _LIBCPP_TEMPLATE_VIS pair
# endif

# if _LIBCPP_STD_VER >= 23
// TODO: Remove this workaround in LLVM 20. The bug got fixed in Clang 18.
// This is a workaround for http://llvm.org/PR60710. We should be able to remove it once Clang is fixed.
template <class _PairLike>
_LIBCPP_HIDE_FROM_ABI static constexpr bool __pair_like_explicit_wknd() {
if constexpr (__pair_like<_PairLike>) {
if constexpr (__pair_like_no_subrange<_PairLike>) {
return !is_convertible_v<decltype(std::get<0>(std::declval<_PairLike&&>())), first_type> ||
!is_convertible_v<decltype(std::get<1>(std::declval<_PairLike&&>())), second_type>;
}
return false;
}

template <__pair_like _PairLike>
requires(!__is_specialization_of_subrange<remove_cvref_t<_PairLike>>::value &&
is_constructible_v<first_type, decltype(std::get<0>(std::declval<_PairLike &&>()))> &&
template <__pair_like_no_subrange _PairLike>
requires(is_constructible_v<first_type, decltype(std::get<0>(std::declval<_PairLike &&>()))> &&
is_constructible_v<second_type, decltype(std::get<1>(std::declval<_PairLike &&>()))>)
_LIBCPP_HIDE_FROM_ABI constexpr explicit(__pair_like_explicit_wknd<_PairLike>()) pair(_PairLike&& __p)
: first(std::get<0>(std::forward<_PairLike>(__p))), second(std::get<1>(std::forward<_PairLike>(__p))) {}
Expand Down Expand Up @@ -306,8 +297,8 @@ struct _LIBCPP_TEMPLATE_VIS pair
return *this;
}

template <__pair_like _PairLike>
requires(__different_from<_PairLike, pair> && !__is_specialization_of_subrange<remove_cvref_t<_PairLike>>::value &&
template <__pair_like_no_subrange _PairLike>
requires(__different_from<_PairLike, pair> &&
is_assignable_v<first_type&, decltype(std::get<0>(std::declval<_PairLike>()))> &&
is_assignable_v<second_type&, decltype(std::get<1>(std::declval<_PairLike>()))>)
_LIBCPP_HIDE_FROM_ABI constexpr pair& operator=(_PairLike&& __p) {
Expand All @@ -316,8 +307,8 @@ struct _LIBCPP_TEMPLATE_VIS pair
return *this;
}

template <__pair_like _PairLike>
requires(__different_from<_PairLike, pair> && !__is_specialization_of_subrange<remove_cvref_t<_PairLike>>::value &&
template <__pair_like_no_subrange _PairLike>
requires(__different_from<_PairLike, pair> &&
is_assignable_v<first_type const&, decltype(std::get<0>(std::declval<_PairLike>()))> &&
is_assignable_v<second_type const&, decltype(std::get<1>(std::declval<_PairLike>()))>)
_LIBCPP_HIDE_FROM_ABI constexpr pair const& operator=(_PairLike&& __p) const {
Expand Down
2 changes: 1 addition & 1 deletion libcxx/include/libcxx.imp
Original file line number Diff line number Diff line change
Expand Up @@ -705,12 +705,12 @@
{ include: [ "<__thread/timed_backoff_policy.h>", "private", "<thread>", "public" ] },
{ include: [ "<__tuple/find_index.h>", "private", "<tuple>", "public" ] },
{ include: [ "<__tuple/make_tuple_types.h>", "private", "<tuple>", "public" ] },
{ include: [ "<__tuple/pair_like.h>", "private", "<tuple>", "public" ] },
{ include: [ "<__tuple/sfinae_helpers.h>", "private", "<tuple>", "public" ] },
{ include: [ "<__tuple/tuple_element.h>", "private", "<tuple>", "public" ] },
{ include: [ "<__tuple/tuple_indices.h>", "private", "<tuple>", "public" ] },
{ include: [ "<__tuple/tuple_like.h>", "private", "<tuple>", "public" ] },
{ include: [ "<__tuple/tuple_like_ext.h>", "private", "<tuple>", "public" ] },
{ include: [ "<__tuple/tuple_like_no_subrange.h>", "private", "<tuple>", "public" ] },
{ include: [ "<__tuple/tuple_size.h>", "private", "<tuple>", "public" ] },
{ include: [ "<__tuple/tuple_types.h>", "private", "<tuple>", "public" ] },
{ include: [ "<__type_traits/add_const.h>", "private", "<type_traits>", "public" ] },
Expand Down
30 changes: 16 additions & 14 deletions libcxx/include/module.modulemap
Original file line number Diff line number Diff line change
Expand Up @@ -1810,20 +1810,22 @@ module std_private_thread_thread [system] {
}
module std_private_thread_timed_backoff_policy [system] { header "__thread/timed_backoff_policy.h" }

module std_private_tuple_find_index [system] { header "__tuple/find_index.h" }
module std_private_tuple_make_tuple_types [system] { header "__tuple/make_tuple_types.h" }
module std_private_tuple_pair_like [system] {
header "__tuple/pair_like.h"
export std_private_tuple_tuple_like
}
module std_private_tuple_sfinae_helpers [system] { header "__tuple/sfinae_helpers.h" }
module std_private_tuple_tuple_element [system] { header "__tuple/tuple_element.h" }
module std_private_tuple_tuple_fwd [system] { header "__fwd/tuple.h" }
module std_private_tuple_tuple_indices [system] { header "__tuple/tuple_indices.h" }
module std_private_tuple_tuple_like [system] { header "__tuple/tuple_like.h" }
module std_private_tuple_tuple_like_ext [system] { header "__tuple/tuple_like_ext.h" }
module std_private_tuple_tuple_size [system] { header "__tuple/tuple_size.h" }
module std_private_tuple_tuple_types [system] { header "__tuple/tuple_types.h" }
module std_private_tuple_find_index [system] { header "__tuple/find_index.h" }
module std_private_tuple_make_tuple_types [system] { header "__tuple/make_tuple_types.h" }
module std_private_tuple_tuple_like_no_subrange [system] {
header "__tuple/tuple_like_no_subrange.h"
}
module std_private_tuple_sfinae_helpers [system] { header "__tuple/sfinae_helpers.h" }
module std_private_tuple_tuple_element [system] { header "__tuple/tuple_element.h" }
module std_private_tuple_tuple_fwd [system] { header "__fwd/tuple.h" }
module std_private_tuple_tuple_indices [system] { header "__tuple/tuple_indices.h" }
module std_private_tuple_tuple_like [system] {
header "__tuple/tuple_like.h"
export *
}
module std_private_tuple_tuple_like_ext [system] { header "__tuple/tuple_like_ext.h" }
module std_private_tuple_tuple_size [system] { header "__tuple/tuple_size.h" }
module std_private_tuple_tuple_types [system] { header "__tuple/tuple_types.h" }

module std_private_type_traits_add_const [system] { header "__type_traits/add_const.h" }
module std_private_type_traits_add_cv [system] { header "__type_traits/add_cv.h" }
Expand Down
2 changes: 2 additions & 0 deletions libcxx/include/variant
Original file line number Diff line number Diff line change
Expand Up @@ -235,11 +235,13 @@ namespace std {
#include <__type_traits/is_destructible.h>
#include <__type_traits/is_nothrow_assignable.h>
#include <__type_traits/is_nothrow_constructible.h>
#include <__type_traits/is_reference.h>
#include <__type_traits/is_trivially_assignable.h>
#include <__type_traits/is_trivially_constructible.h>
#include <__type_traits/is_trivially_destructible.h>
#include <__type_traits/is_void.h>
#include <__type_traits/remove_const.h>
#include <__type_traits/remove_cvref.h>
#include <__type_traits/type_identity.h>
#include <__type_traits/void_t.h>
#include <__utility/declval.h>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
// template<class T>
// concept tuple-like; // exposition only

#include <__tuple/tuple_like.h>
#include <array>
#include <complex>
#include <ranges>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ static_assert(!std::ranges::input_range<Range<cpp20_output_iterator<std::tuple<i
static_assert(!HasElementsView<Range<cpp20_output_iterator<std::tuple<int>*>>, 0>);

// !tuple-like
LIBCPP_STATIC_ASSERT(!std::__tuple_like<int>);
static_assert(!HasElementsView<Range<int*>, 1>);

// !(N < tuple_size_v<T>)
Expand Down