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

P2165R4: Compatibility Between tuple, pair, And tuple-like Objects (changes to pair only) #3323

Merged
merged 16 commits into from
Jan 22, 2023
Merged
Show file tree
Hide file tree
Changes from 12 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
3 changes: 3 additions & 0 deletions stl/inc/__msvc_iter_core.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,9 @@ namespace ranges {

_EXPORT_STD using ranges::get;

template <class _It, class _Se, ranges::subrange_kind _Ki>
inline constexpr bool _Is_subrange_v<ranges::subrange<_It, _Se, _Ki>> = true;

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

Expand Down
9 changes: 2 additions & 7 deletions stl/inc/ranges
Original file line number Diff line number Diff line change
Expand Up @@ -2694,11 +2694,6 @@ namespace ranges {
inline constexpr bool enable_borrowed_range<take_view<_Rng>> = enable_borrowed_range<_Rng>;

namespace views {
template <class>
inline constexpr bool _Is_subrange = false;
template <class _It, class _Se, subrange_kind _Ki>
inline constexpr bool _Is_subrange<subrange<_It, _Se, _Ki>> = true;

template <class _Rng>
concept _Random_sized_range = random_access_range<_Rng> && sized_range<_Rng>;

Expand Down Expand Up @@ -2726,7 +2721,7 @@ namespace ranges {
} else if constexpr (_Random_sized_range<_Ty> && _Is_specialization_v<_Ty, iota_view>) {
return {_St::_Reconstruct_iota_view,
noexcept(_RANGES begin(_STD declval<_Rng&>()) + _RANGES distance(_STD declval<_Rng&>()))};
} else if constexpr (_Random_sized_range<_Ty> && _Is_subrange<_Ty>) {
} else if constexpr (_Random_sized_range<_Ty> && _Is_subrange_v<_Ty>) {
return {_St::_Reconstruct_subrange,
noexcept(subrange(_RANGES begin(_STD declval<_Rng&>()),
_RANGES begin(_STD declval<_Rng&>()) + _RANGES distance(_STD declval<_Rng&>())))};
Expand Down Expand Up @@ -3094,7 +3089,7 @@ namespace ranges {
return {_St::_Reconstruct_span, true};
} else if constexpr (_Is_specialization_v<_Ty, basic_string_view>) {
return {_St::_Reconstruct_other, true};
} else if constexpr (_Random_sized_range<_Ty> && _Is_subrange<_Ty>) {
} else if constexpr (_Random_sized_range<_Ty> && _Is_subrange_v<_Ty>) {
if constexpr (sized_sentinel_for<sentinel_t<_Ty>, iterator_t<_Ty>>) {
return {_St::_Reconstruct_subrange,
noexcept(_Ty(_RANGES begin(_STD declval<_Rng&>()) + _RANGES distance(_STD declval<_Rng&>()),
Expand Down
9 changes: 0 additions & 9 deletions stl/inc/span
Original file line number Diff line number Diff line change
Expand Up @@ -222,9 +222,6 @@ struct _Span_extent_type<_Ty, dynamic_extent> {
size_t _Mysize{0};
};

_EXPORT_STD template <class _Ty, size_t _Size>
class array;

_EXPORT_STD template <class _Ty, size_t _Extent>
class span;

Expand All @@ -242,12 +239,6 @@ inline constexpr bool _Is_span_v = false;
template <class _Ty, size_t _Extent>
inline constexpr bool _Is_span_v<span<_Ty, _Extent>> = true;

template <class>
inline constexpr bool _Is_std_array_v = false;

template <class _Ty, size_t _Size>
inline constexpr bool _Is_std_array_v<array<_Ty, _Size>> = true;

// clang-format off
template <class _It, class _Ty>
concept _Span_compatible_iterator = contiguous_iterator<_It>
Expand Down
18 changes: 0 additions & 18 deletions stl/inc/tuple
Original file line number Diff line number Diff line change
Expand Up @@ -179,9 +179,6 @@ struct _Alloc_unpack_tuple_t {
explicit _Alloc_unpack_tuple_t() = default;
}; // tag type to disambiguate construction (from an allocator and unpacking a tuple/pair)

_EXPORT_STD template <class... _Types>
class tuple;

template <>
class tuple<> { // empty tuple
public:
Expand Down Expand Up @@ -824,21 +821,6 @@ _NODISCARD constexpr tuple<_Types&&...> forward_as_tuple(_Types&&... _Args) noex
return tuple<_Types&&...>(_STD forward<_Types>(_Args)...);
}

_EXPORT_STD template <class _Ty, size_t _Size>
class array;

_EXPORT_STD template <size_t _Idx, class _Ty, size_t _Size>
_NODISCARD constexpr _Ty& get(array<_Ty, _Size>& _Arr) noexcept;

_EXPORT_STD template <size_t _Idx, class _Ty, size_t _Size>
_NODISCARD constexpr const _Ty& get(const array<_Ty, _Size>& _Arr) noexcept;

_EXPORT_STD template <size_t _Idx, class _Ty, size_t _Size>
_NODISCARD constexpr _Ty&& get(array<_Ty, _Size>&& _Arr) noexcept;

_EXPORT_STD template <size_t _Idx, class _Ty, size_t _Size>
_NODISCARD constexpr const _Ty&& get(const array<_Ty, _Size>&& _Arr) noexcept;

template <class _Ty, class _Kx_arg, class _Ix_arg, size_t _Ix_next, class... _Sequences>
struct _Tuple_cat2;

Expand Down
134 changes: 118 additions & 16 deletions stl/inc/utility
Original file line number Diff line number Diff line change
Expand Up @@ -134,12 +134,87 @@ struct uses_allocator : _Has_allocator_type<_Ty, _Alloc>::type {
_EXPORT_STD template <class _Ty, class _Alloc>
_INLINE_VAR constexpr bool uses_allocator_v = uses_allocator<_Ty, _Alloc>::value;

_EXPORT_STD template <class...>
_EXPORT_STD template <class... _Types>
class tuple;

_EXPORT_STD template <class _Ty1, class _Ty2>
struct pair;

_EXPORT_STD template <class _Ty, size_t _Size>
class array;

_EXPORT_STD template <class _Tuple>
struct tuple_size;

_EXPORT_STD template <class _Ty>
_INLINE_VAR constexpr size_t tuple_size_v = tuple_size<_Ty>::value;

_EXPORT_STD template <size_t _Index, class _Tuple>
struct tuple_element;

_EXPORT_STD template <size_t _Index, class _Tuple>
using tuple_element_t = typename tuple_element<_Index, _Tuple>::type;

_EXPORT_STD /* TRANSITION, VSO-1538698 */ template <size_t _Index, class... _Types>
_NODISCARD constexpr auto&& _Tuple_get(tuple<_Types...>&& _Tuple) noexcept;

_EXPORT_STD template <size_t _Index, class... _Types>
_NODISCARD constexpr tuple_element_t<_Index, tuple<_Types...>>& get(tuple<_Types...>& _Tuple) noexcept;

_EXPORT_STD template <size_t _Index, class... _Types>
_NODISCARD constexpr const tuple_element_t<_Index, tuple<_Types...>>& get(const tuple<_Types...>& _Tuple) noexcept;

_EXPORT_STD template <size_t _Index, class... _Types>
_NODISCARD constexpr tuple_element_t<_Index, tuple<_Types...>>&& get(tuple<_Types...>&& _Tuple) noexcept;

_EXPORT_STD template <size_t _Index, class... _Types>
_NODISCARD constexpr const tuple_element_t<_Index, tuple<_Types...>>&& get(const tuple<_Types...>&& _Tuple) noexcept;

_EXPORT_STD template <size_t _Idx, class _Ty, size_t _Size>
_NODISCARD constexpr _Ty& get(array<_Ty, _Size>& _Arr) noexcept;

_EXPORT_STD template <size_t _Idx, class _Ty, size_t _Size>
_NODISCARD constexpr const _Ty& get(const array<_Ty, _Size>& _Arr) noexcept;

_EXPORT_STD template <size_t _Idx, class _Ty, size_t _Size>
_NODISCARD constexpr _Ty&& get(array<_Ty, _Size>&& _Arr) noexcept;

_EXPORT_STD template <size_t _Idx, class _Ty, size_t _Size>
_NODISCARD constexpr const _Ty&& get(const array<_Ty, _Size>&& _Arr) noexcept;

#ifdef __cpp_lib_concepts
template <class _Ty1, class _Ty2>
concept _Different_from = (!same_as<remove_cvref_t<_Ty1>, remove_cvref_t<_Ty2>>);

template <class>
inline constexpr bool _Is_std_array_v = false;

template <class _Ty, size_t _Size>
inline constexpr bool _Is_std_array_v<array<_Ty, _Size>> = true;

template <class>
inline constexpr bool _Is_subrange_v = false;

#if _HAS_CXX23
template <class _Ty>
inline constexpr bool _Tuple_like_impl =
_Is_specialization_v<_Ty, tuple> || _Is_specialization_v<_Ty, pair> || _Is_std_array_v<_Ty> || _Is_subrange_v<_Ty>;

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

template <class _Ty>
concept _Pair_like = _Tuple_like<_Ty> && tuple_size_v<remove_cvref_t<_Ty>> == 2;
JMazurkiewicz marked this conversation as resolved.
Show resolved Hide resolved

#ifdef __clang__ // TRANSITION, LLVM-59827
template <class _PairLike, class _Ty1, class _Ty2>
concept _Can_construct_from_pair_like =
_Pair_like<_PairLike> && is_constructible_v<_Ty1, decltype(_STD get<0>(_STD declval<_PairLike>()))>
&& is_constructible_v<_Ty2, decltype(_STD get<1>(_STD declval<_PairLike>()))>;
#endif // __clang__
#endif // _HAS_CXX23
#endif // __cpp_lib_concepts

_EXPORT_STD template <class _Ty1, class _Ty2>
struct pair { // store a pair of values
using first_type = _Ty1;
Expand Down Expand Up @@ -207,6 +282,22 @@ struct pair { // store a pair of values
pair(const pair<_Other1, _Other2>&& _Right) noexcept(is_nothrow_constructible_v<_Ty1, const _Other1>&&
is_nothrow_constructible_v<_Ty2, const _Other2>) // strengthened
: first(_STD forward<const _Other1>(_Right.first)), second(_STD forward<const _Other2>(_Right.second)) {}

#ifdef __cpp_lib_concepts
#ifdef __clang__ // TRANSITION, LLVM-59827
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<is_constructible<_Ty1, decltype(_STD get<0>(_STD declval<_Other>()))>,
is_constructible<_Ty2, decltype(_STD get<1>(_STD declval<_Other>()))>>
#endif // __clang__
constexpr explicit(!conjunction_v<is_convertible<decltype(_STD get<0>(_STD declval<_Other>())), _Ty1>,
is_convertible<decltype(_STD get<1>(_STD declval<_Other>())), _Ty2>>)
pair(_Other&& _Right) noexcept(is_nothrow_constructible_v<_Ty1, decltype(_STD get<0>(_STD declval<_Other>()))>&&
is_nothrow_constructible_v<_Ty2, decltype(_STD get<1>(_STD declval<_Other>()))>) // strengthened
: first(_STD get<0>(_STD forward<_Other>(_Right))), second(_STD get<1>(_STD forward<_Other>(_Right))) {
}
#endif // __cpp_lib_concepts
#endif // _HAS_CXX23

template <class _Tuple1, class _Tuple2, size_t... _Indexes1, size_t... _Indexes2>
Expand Down Expand Up @@ -318,6 +409,32 @@ struct pair { // store a pair of values
second = _STD forward<_Other2>(_Right.second);
return *this;
}

#ifdef __cpp_lib_concepts
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>()))>
&& 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>()))>&&
is_nothrow_assignable_v<_Ty2&, decltype(_STD get<1>(_STD declval<_Other>()))>) /* strengthened */ {
first = _STD get<0>(_STD forward<_Other>(_Right));
second = _STD get<1>(_STD forward<_Other>(_Right));
return *this;
}

template <_Pair_like _Other>
requires _Different_from<_Other, pair> && (!_Is_subrange_v<remove_cvref_t<_Other>>)
&& 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(
is_nothrow_assignable_v<const _Ty1&, decltype(_STD get<0>(_STD declval<_Other>()))>&&
is_nothrow_assignable_v<const _Ty2&, decltype(_STD get<1>(_STD declval<_Other>()))>) /* strengthened */ {
first = _STD get<0>(_STD forward<_Other>(_Right));
second = _STD get<1>(_STD forward<_Other>(_Right));
return *this;
}
#endif // __cpp_lib_concepts
#endif // _HAS_CXX23

_CONSTEXPR20 void swap(pair& _Right) noexcept(
Expand Down Expand Up @@ -469,9 +586,6 @@ namespace _CXX20_DEPRECATE_REL_OPS rel_ops {
}
} // namespace _CXX20_DEPRECATE_REL_OPS rel_ops

_EXPORT_STD template <class _Tuple>
struct tuple_size;

template <class _Tuple, class = void>
struct _Tuple_size_sfinae {}; // selected when tuple_size<_Tuple>::value isn't well-formed

Expand All @@ -488,12 +602,6 @@ struct _CXX20_DEPRECATE_VOLATILE tuple_size<volatile _Tuple> : _Tuple_size_sfina
template <class _Tuple>
struct _CXX20_DEPRECATE_VOLATILE tuple_size<const volatile _Tuple> : _Tuple_size_sfinae<_Tuple> {}; // ignore cv

_EXPORT_STD template <class _Ty>
_INLINE_VAR constexpr size_t tuple_size_v = tuple_size<_Ty>::value;

_EXPORT_STD template <size_t _Index, class _Tuple>
struct tuple_element;

template <size_t _Index, class _Tuple>
struct _MSVC_KNOWN_SEMANTICS tuple_element<_Index, const _Tuple> : tuple_element<_Index, _Tuple> {
using _Mybase = tuple_element<_Index, _Tuple>;
Expand All @@ -514,12 +622,6 @@ struct _CXX20_DEPRECATE_VOLATILE _MSVC_KNOWN_SEMANTICS tuple_element<_Index, con
using type = add_cv_t<typename _Mybase::type>;
};

_EXPORT_STD template <size_t _Index, class _Tuple>
using tuple_element_t = typename tuple_element<_Index, _Tuple>::type;

_EXPORT_STD template <class _Ty, size_t _Size>
class array;

template <class _Ty, size_t _Size>
struct tuple_size<array<_Ty, _Size>> : integral_constant<size_t, _Size> {}; // size of array

Expand Down
3 changes: 0 additions & 3 deletions stl/inc/xutility
Original file line number Diff line number Diff line change
Expand Up @@ -1762,9 +1762,6 @@ _NODISCARD constexpr const _Elem* data(initializer_list<_Elem> _Ilist) noexcept
}

#ifdef __cpp_lib_concepts
template <class _Ty1, class _Ty2>
concept _Different_from = (!same_as<remove_cvref_t<_Ty1>, remove_cvref_t<_Ty2>>);

#if _HAS_CXX23
_EXPORT_STD template <indirectly_readable _Ty>
using iter_const_reference_t = common_reference_t<const iter_value_t<_Ty>&&, iter_reference_t<_Ty>>;
Expand Down
2 changes: 1 addition & 1 deletion stl/inc/yvals_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@
// P2077R3 Heterogeneous Erasure Overloads For Associative Containers
// P2136R3 invoke_r()
// P2165R4 Compatibility Between tuple, pair, And tuple-like Objects
// (changes to views::zip only)
// (changes to views::zip and pair only)
// P2166R1 Prohibiting basic_string And basic_string_view Construction From nullptr
// P2186R2 Removing Garbage Collection Support
// P2273R3 constexpr unique_ptr
Expand Down
1 change: 1 addition & 0 deletions tests/std/test.lst
Original file line number Diff line number Diff line change
Expand Up @@ -550,6 +550,7 @@ tests\P1899R3_views_stride_death
tests\P1951R1_default_arguments_pair_forward_ctor
tests\P2136R3_invoke_r
tests\P2162R2_std_visit_for_derived_classes_from_variant
tests\P2165R4_tuple_like_pair
tests\P2231R1_complete_constexpr_optional_variant
tests\P2273R3_constexpr_unique_ptr
tests\P2278R4_basic_const_iterator
Expand Down
4 changes: 4 additions & 0 deletions tests/std/tests/P2165R4_tuple_like_pair/env.lst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

RUNALL_INCLUDE ..\strict_concepts_latest_matrix.lst
JMazurkiewicz marked this conversation as resolved.
Show resolved Hide resolved
Loading