Skip to content
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

Refactoring around tuple-like, pair-like, and subrange #4983

Merged
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
5 changes: 0 additions & 5 deletions stl/inc/__msvc_iter_core.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -438,11 +438,6 @@ _EXPORT_STD using ranges::get;
template <class _It, class _Se, ranges::subrange_kind _Ki>
constexpr bool _Is_subrange_v<ranges::subrange<_It, _Se, _Ki>> = true;

#if _HAS_CXX23
template <class _It, class _Se, ranges::subrange_kind _Ki>
constexpr bool _Tuple_like_impl<ranges::subrange<_It, _Se, _Ki>> = true;
#endif // _HAS_CXX23

template <class _It, class _Se, ranges::subrange_kind _Ki>
struct tuple_size<ranges::subrange<_It, _Se, _Ki>> : integral_constant<size_t, 2> {};

Expand Down
25 changes: 10 additions & 15 deletions stl/inc/tuple
Original file line number Diff line number Diff line change
Expand Up @@ -177,13 +177,12 @@ constexpr bool _Can_construct_values_from_tuple_like_v<tuple<_Types...>, _Other,

#ifdef __EDG__ // TRANSITION, VSO-1900279
template <class _TupleLike, class _Tuple>
concept _Can_construct_from_tuple_like =
_Different_from<_TupleLike, _Tuple> && _Tuple_like<_TupleLike> && !_Is_subrange_v<remove_cvref_t<_TupleLike>>
&& (tuple_size_v<_Tuple> == tuple_size_v<remove_cvref_t<_TupleLike>>) //
&&_Can_construct_values_from_tuple_like_v<_Tuple, _TupleLike>
&& (tuple_size_v<_Tuple> != 1
|| (!is_convertible_v<_TupleLike, tuple_element_t<0, _Tuple>>
&& !is_constructible_v<tuple_element_t<0, _Tuple>, _TupleLike>) );
concept _Can_construct_from_tuple_like = _Different_from<_TupleLike, _Tuple> && _Tuple_like_non_subrange<_TupleLike>
&& (tuple_size_v<_Tuple> == tuple_size_v<remove_cvref_t<_TupleLike>>)
&& _Can_construct_values_from_tuple_like_v<_Tuple, _TupleLike>
&& (tuple_size_v<_Tuple> != 1
|| (!is_convertible_v<_TupleLike, tuple_element_t<0, _Tuple>>
&& !is_constructible_v<tuple_element_t<0, _Tuple>, _TupleLike>) );
#endif // ^^^ workaround ^^^

template <class _TTuple, class _UTuple, class _Indices = make_index_sequence<tuple_size_v<_UTuple>>>
Expand Down Expand Up @@ -421,8 +420,7 @@ public:
template <class _Other, enable_if_t<_Can_construct_from_tuple_like<_Other, tuple>, int> = 0>
#else // ^^^ workaround / no workaround vvv
template <_Different_from<tuple> _Other>
requires _Tuple_like<_Other> && (!_Is_subrange_v<remove_cvref_t<_Other>>)
&& (1 + sizeof...(_Rest) == tuple_size_v<remove_cvref_t<_Other>>)
requires _Tuple_like_non_subrange<_Other> && (1 + sizeof...(_Rest) == tuple_size_v<remove_cvref_t<_Other>>)
&& _Can_construct_values_from_tuple_like_v<tuple, _Other>
&& (sizeof...(_Rest) != 0 || (!is_convertible_v<_Other, _This> && !is_constructible_v<_This, _Other>) )
#endif // ^^^ no workaround ^^^
Expand Down Expand Up @@ -527,8 +525,7 @@ public:
template <class _Alloc, class _Other, enable_if_t<_Can_construct_from_tuple_like<_Other, tuple>, int> = 0>
#else // ^^^ workaround / no workaround vvv
template <class _Alloc, _Different_from<tuple> _Other>
requires _Tuple_like<_Other> && (!_Is_subrange_v<remove_cvref_t<_Other>>)
&& (1 + sizeof...(_Rest) == tuple_size_v<remove_cvref_t<_Other>>)
requires _Tuple_like_non_subrange<_Other> && (1 + sizeof...(_Rest) == tuple_size_v<remove_cvref_t<_Other>>)
&& _Can_construct_values_from_tuple_like_v<tuple, _Other>
&& (sizeof...(_Rest) != 0 || (!is_convertible_v<_Other, _This> && !is_constructible_v<_This, _Other>) )
#endif // ^^^ no workaround ^^^
Expand Down Expand Up @@ -692,17 +689,15 @@ public:
}

template <_Different_from<tuple> _Other>
requires _Tuple_like<_Other> && (!_Is_subrange_v<remove_cvref_t<_Other>>)
&& (1 + sizeof...(_Rest) == tuple_size_v<remove_cvref_t<_Other>>)
requires _Tuple_like_non_subrange<_Other> && (1 + sizeof...(_Rest) == tuple_size_v<remove_cvref_t<_Other>>)
&& _Can_assign_values_from_tuple_like_v<false, _Other>
constexpr tuple& operator=(_Other&& _Right) {
_Assign_tuple_like(_STD forward<_Other>(_Right), make_index_sequence<1 + sizeof...(_Rest)>{});
return *this;
}

template <_Different_from<tuple> _Other>
requires _Tuple_like<_Other> && (!_Is_subrange_v<remove_cvref_t<_Other>>)
&& (1 + sizeof...(_Rest) == tuple_size_v<remove_cvref_t<_Other>>)
requires _Tuple_like_non_subrange<_Other> && (1 + sizeof...(_Rest) == tuple_size_v<remove_cvref_t<_Other>>)
&& _Can_assign_values_from_tuple_like_v<true, _Other>
constexpr const tuple& operator=(_Other&& _Right) const {
_Assign_tuple_like(_STD forward<_Other>(_Right), make_index_sequence<1 + sizeof...(_Rest)>{});
Expand Down
35 changes: 18 additions & 17 deletions stl/inc/utility
Original file line number Diff line number Diff line change
Expand Up @@ -205,28 +205,31 @@ constexpr bool _Is_subrange_v = false;

#if _HAS_CXX23
template <class>
constexpr bool _Tuple_like_impl = false;
constexpr bool _Tuple_like_non_subrange_impl = false;

template <class... _Types>
constexpr bool _Tuple_like_impl<tuple<_Types...>> = true;
constexpr bool _Tuple_like_non_subrange_impl<tuple<_Types...>> = true;

template <class _Ty1, class _Ty2>
constexpr bool _Tuple_like_impl<pair<_Ty1, _Ty2>> = true;
constexpr bool _Tuple_like_non_subrange_impl<pair<_Ty1, _Ty2>> = true;

template <class _Ty, size_t _Size>
constexpr bool _Tuple_like_impl<array<_Ty, _Size>> = true;
constexpr bool _Tuple_like_non_subrange_impl<array<_Ty, _Size>> = true;

template <class _Ty>
concept _Tuple_like = _Tuple_like_impl<remove_cvref_t<_Ty>>;
concept _Tuple_like_non_subrange = _Tuple_like_non_subrange_impl<remove_cvref_t<_Ty>>;

template <class _Ty>
concept _Pair_like = _Tuple_like<_Ty> && tuple_size_v<remove_cvref_t<_Ty>> == 2;
concept _Tuple_like = _Tuple_like_non_subrange<_Ty> || _Is_subrange_v<remove_cvref_t<_Ty>>;

template <class _Ty>
concept _Pair_like_non_subrange = _Tuple_like_non_subrange<_Ty> && tuple_size_v<remove_cvref_t<_Ty>> == 2;

#ifdef __EDG__ // TRANSITION, VSO-1900279
template <class _PairLike, class _Ty1, class _Ty2>
concept _Can_construct_from_pair_like = _Pair_like<_PairLike> && !_Is_subrange_v<remove_cvref_t<_PairLike>>
&& is_constructible_v<_Ty1, decltype(_STD get<0>(_STD declval<_PairLike>()))>
&& is_constructible_v<_Ty2, decltype(_STD get<1>(_STD declval<_PairLike>()))>;
concept _Can_construct_from_pair_like =
_Pair_like_non_subrange<_PairLike> && is_constructible_v<_Ty1, decltype(_STD get<0>(_STD declval<_PairLike>()))>
&& is_constructible_v<_Ty2, decltype(_STD get<1>(_STD declval<_PairLike>()))>;
#endif // ^^^ workaround ^^^
#endif // _HAS_CXX23
#endif // _HAS_CXX20
Expand Down Expand Up @@ -302,9 +305,8 @@ struct pair { // store a pair of values
#ifdef __EDG__ // TRANSITION, VSO-1900279
template <class _Other, enable_if_t<_Can_construct_from_pair_like<_Other, _Ty1, _Ty2>, int> = 0>
#else // ^^^ workaround / no workaround vvv
template <_Pair_like _Other>
requires conjunction_v<bool_constant<!_Is_subrange_v<remove_cvref_t<_Other>>>,
is_constructible<_Ty1, decltype(_STD get<0>(_STD declval<_Other>()))>,
template <_Pair_like_non_subrange _Other>
requires conjunction_v<is_constructible<_Ty1, decltype(_STD get<0>(_STD declval<_Other>()))>,
is_constructible<_Ty2, decltype(_STD get<1>(_STD declval<_Other>()))>>
#endif // ^^^ no workaround ^^^
constexpr explicit(!conjunction_v<is_convertible<decltype(_STD get<0>(_STD declval<_Other>())), _Ty1>,
Expand Down Expand Up @@ -422,9 +424,8 @@ struct pair { // store a pair of values
return *this;
}

template <_Pair_like _Other>
requires _Different_from<_Other, pair> && (!_Is_subrange_v<remove_cvref_t<_Other>>)
&& is_assignable_v<_Ty1&, decltype(_STD get<0>(_STD declval<_Other>()))>
template <_Pair_like_non_subrange _Other>
requires _Different_from<_Other, pair> && is_assignable_v<_Ty1&, decltype(_STD get<0>(_STD declval<_Other>()))>
&& is_assignable_v<_Ty2&, decltype(_STD get<1>(_STD declval<_Other>()))>
constexpr pair& operator=(_Other&& _Right)
noexcept(is_nothrow_assignable_v<_Ty1&, decltype(_STD get<0>(_STD declval<_Other>()))>
Expand All @@ -434,8 +435,8 @@ struct pair { // store a pair of values
return *this;
}

template <_Pair_like _Other>
requires _Different_from<_Other, pair> && (!_Is_subrange_v<remove_cvref_t<_Other>>)
template <_Pair_like_non_subrange _Other>
requires _Different_from<_Other, pair>
&& is_assignable_v<const _Ty1&, decltype(_STD get<0>(_STD declval<_Other>()))>
&& is_assignable_v<const _Ty2&, decltype(_STD get<1>(_STD declval<_Other>()))>
constexpr const pair& operator=(_Other&& _Right) const noexcept(
Expand Down
2 changes: 1 addition & 1 deletion stl/inc/xmemory
Original file line number Diff line number Diff line change
Expand Up @@ -2435,7 +2435,7 @@ _NODISCARD constexpr auto uses_allocator_construction_args(
_EXPORT_STD template <_Cv_std_pair _Ty, class _Alloc, _Usable_for_pair_like_overload _Uty>
_NODISCARD constexpr auto uses_allocator_construction_args(const _Alloc& _Al, _Uty&& _Ux) noexcept {
#if _HAS_CXX23
if constexpr (_Pair_like<_Uty> && !_Is_subrange_v<remove_cvref_t<_Uty>>) {
if constexpr (_Pair_like_non_subrange<_Uty>) {
// equivalent to
// return _STD uses_allocator_construction_args<_Ty>(_Al, piecewise_construct,
// _STD forward_as_tuple(_STD get<0>(_STD forward<_Uty>(_Ux)),
Expand Down
35 changes: 19 additions & 16 deletions stl/inc/xutility
Original file line number Diff line number Diff line change
Expand Up @@ -3874,6 +3874,21 @@ namespace ranges {
};
} // namespace ranges

#if _HAS_CXX23
template <class _Ty>
concept _Pair_like = _Tuple_like<_Ty> && tuple_size_v<remove_cvref_t<_Ty>> == 2;
#else // ^^^ _HAS_CXX23 / !_HAS_CXX23 vvv
template <class _Ty>
concept _Pair_like = !is_reference_v<_Ty> && requires(_Ty __t) {
typename tuple_size<_Ty>::type;
requires derived_from<tuple_size<_Ty>, integral_constant<size_t, 2>>;
typename tuple_element_t<0, remove_const_t<_Ty>>;
typename tuple_element_t<1, remove_const_t<_Ty>>;
{ _STD get<0>(__t) } -> convertible_to<const tuple_element_t<0, _Ty>&>;
{ _STD get<1>(__t) } -> convertible_to<const tuple_element_t<1, _Ty>&>;
};
#endif // ^^^ !_HAS_CXX23 ^^^

namespace ranges {
template <class _From, class _To>
concept _Uses_nonqualification_pointer_conversion =
Expand All @@ -3884,18 +3899,6 @@ namespace ranges {
concept _Convertible_to_non_slicing =
convertible_to<_From, _To> && !_Uses_nonqualification_pointer_conversion<decay_t<_From>, decay_t<_To>>;

#if !_HAS_CXX23
template <class _Ty>
concept _Pair_like = !is_reference_v<_Ty> && requires(_Ty __t) {
typename tuple_size<_Ty>::type;
requires derived_from<tuple_size<_Ty>, integral_constant<size_t, 2>>;
typename tuple_element_t<0, remove_const_t<_Ty>>;
typename tuple_element_t<1, remove_const_t<_Ty>>;
{ _STD get<0>(__t) } -> convertible_to<const tuple_element_t<0, _Ty>&>;
{ _STD get<1>(__t) } -> convertible_to<const tuple_element_t<1, _Ty>&>;
};
#endif // !_HAS_CXX23

template <class _Ty, class _First, class _Second>
concept _Pair_like_convertible_from = !range<_Ty>
#if _HAS_CXX23
Expand Down Expand Up @@ -3989,10 +3992,10 @@ namespace ranges {
requires (_Ki == subrange_kind::sized)
: subrange{_RANGES begin(_Val), _RANGES end(_Val), _Count} {}

template <_Different_from<subrange> _Pair_like>
requires _Pair_like_convertible_from<_Pair_like, const _It&, const _Se&>
constexpr operator _Pair_like() const {
return _Pair_like(_First, _Last);
template <_Different_from<subrange> _PairLike>
requires _Pair_like_convertible_from<_PairLike, const _It&, const _Se&>
constexpr operator _PairLike() const {
return _PairLike(_First, _Last);
}

_NODISCARD constexpr _It begin() const
Expand Down