Skip to content

Commit 7869d61

Browse files
committed
Make pair, tuple and vector<bool>::reference usable as proxy references
1 parent 5a2b58f commit 7869d61

File tree

11 files changed

+685
-8
lines changed

11 files changed

+685
-8
lines changed

stl/inc/tuple

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,8 +219,16 @@ public:
219219
constexpr tuple(_Tag, const _Alloc&) noexcept /* strengthened */ {}
220220

221221
constexpr tuple& operator=(const tuple&) = default;
222+
#if _HAS_CXX23
223+
constexpr const tuple& operator=(const tuple&) const {
224+
return *this;
225+
}
226+
#endif // _HAS_CXX23
222227

223228
_CONSTEXPR20 void swap(tuple&) noexcept {}
229+
#if _HAS_CXX23
230+
constexpr void swap(const tuple&) const noexcept {}
231+
#endif // _HAS_CXX23
224232

225233
constexpr bool _Equals(const tuple&) const noexcept {
226234
return true;
@@ -349,6 +357,15 @@ public:
349357
tuple(const tuple&) = default;
350358
tuple(tuple&&) = default;
351359

360+
#if _HAS_CXX23
361+
template <class... _Other, enable_if_t<conjunction_v<_STD _Tuple_constructible_val<tuple, _Other&...>,
362+
_STD _Tuple_convert_val<tuple, tuple<_Other...>&, _Other...>>,
363+
int> = 0>
364+
constexpr explicit(_Tuple_conditional_explicit_v<tuple, _Other&...>)
365+
tuple(tuple<_Other...>& _Right) noexcept(_Tuple_nothrow_constructible_v<tuple, _Other&...>) // strengthened
366+
: tuple(_Unpack_tuple_t{}, _Right) {}
367+
#endif // _HAS_CXX23
368+
352369
#if _HAS_CONDITIONAL_EXPLICIT
353370
template <class... _Other, enable_if_t<conjunction_v<_STD _Tuple_constructible_val<tuple, const _Other&...>,
354371
_STD _Tuple_convert_val<tuple, const tuple<_Other...>&, _Other...>>,
@@ -396,6 +413,24 @@ public:
396413
: tuple(_Unpack_tuple_t{}, _STD move(_Right)) {}
397414
#endif // ^^^ !_HAS_CONDITIONAL_EXPLICIT ^^^
398415

416+
#if _HAS_CXX23
417+
template <class... _Other, enable_if_t<conjunction_v<_STD _Tuple_constructible_val<tuple, const _Other...>,
418+
_STD _Tuple_convert_val<tuple, const tuple<_Other...>, _Other...>>,
419+
int> = 0>
420+
constexpr explicit(_Tuple_conditional_explicit_v<tuple, const _Other...>)
421+
tuple(const tuple<_Other...>&& _Right) noexcept(
422+
_Tuple_nothrow_constructible_v<tuple, const _Other...>) // strengthened
423+
: tuple(_Unpack_tuple_t{}, _STD move(_Right)) {}
424+
#endif // _HAS_CXX23
425+
426+
#if _HAS_CXX23
427+
template <class _First, class _Second, enable_if_t<_Tuple_constructible_v<tuple, _First&, _Second&>, int> = 0>
428+
constexpr explicit(_Tuple_conditional_explicit_v<tuple, _First&, _Second&>)
429+
tuple(pair<_First, _Second>& _Right) noexcept(
430+
_Tuple_nothrow_constructible_v<tuple, _First&, _Second&>) // strengthened
431+
: tuple(_Unpack_tuple_t{}, _Right) {}
432+
#endif // _HAS_CXX23
433+
399434
#if _HAS_CONDITIONAL_EXPLICIT
400435
template <class _First, class _Second,
401436
enable_if_t<_Tuple_constructible_v<tuple, const _First&, const _Second&>, int> = 0>
@@ -434,6 +469,15 @@ public:
434469
: tuple(_Unpack_tuple_t{}, _STD move(_Right)) {}
435470
#endif // ^^^ !_HAS_CONDITIONAL_EXPLICIT ^^^
436471

472+
#if _HAS_CXX23
473+
template <class _First, class _Second,
474+
enable_if_t<_Tuple_constructible_v<tuple, const _First, const _Second>, int> = 0>
475+
constexpr explicit(_Tuple_conditional_explicit_v<tuple, const _First, const _Second>)
476+
tuple(const pair<_First, _Second>&& _Right) noexcept(
477+
_Tuple_nothrow_constructible_v<tuple, const _First, const _Second>) // strengthened
478+
: tuple(_Unpack_tuple_t{}, _STD move(_Right)) {}
479+
#endif // _HAS_CXX23
480+
437481
#if _HAS_CONDITIONAL_EXPLICIT
438482
template <class _Alloc, class _This2 = _This,
439483
enable_if_t<conjunction_v<_STD is_default_constructible<_This2>, _STD is_default_constructible<_Rest>...>,
@@ -510,6 +554,16 @@ public:
510554
_CONSTEXPR20 tuple(allocator_arg_t, const _Alloc& _Al, tuple&& _Right)
511555
: tuple(_Alloc_unpack_tuple_t{}, _Al, _STD move(_Right)) {}
512556

557+
#if _HAS_CXX23
558+
template <class _Alloc, class... _Other,
559+
enable_if_t<conjunction_v<_STD _Tuple_constructible_val<tuple, _Other&...>,
560+
_STD _Tuple_convert_val<tuple, tuple<_Other...>&, _Other...>>,
561+
int> = 0>
562+
constexpr explicit(_Tuple_conditional_explicit_v<tuple, _Other&...>)
563+
tuple(allocator_arg_t, const _Alloc& _Al, tuple<_Other...>& _Right)
564+
: tuple(_Alloc_unpack_tuple_t{}, _Al, _Right) {}
565+
#endif // _HAS_CXX23
566+
513567
#if _HAS_CONDITIONAL_EXPLICIT
514568
template <class _Alloc, class... _Other,
515569
enable_if_t<conjunction_v<_STD _Tuple_constructible_val<tuple, const _Other&...>,
@@ -558,6 +612,24 @@ public:
558612
: tuple(_Alloc_unpack_tuple_t{}, _Al, _STD move(_Right)) {}
559613
#endif // ^^^ !_HAS_CONDITIONAL_EXPLICIT ^^^
560614

615+
#if _HAS_CXX23
616+
template <class _Alloc, class... _Other,
617+
enable_if_t<conjunction_v<_STD _Tuple_constructible_val<tuple, const _Other...>,
618+
_STD _Tuple_convert_val<tuple, const tuple<_Other...>, _Other...>>,
619+
int> = 0>
620+
constexpr explicit(_Tuple_conditional_explicit_v<tuple, const _Other...>)
621+
tuple(allocator_arg_t, const _Alloc& _Al, const tuple<_Other...>&& _Right)
622+
: tuple(_Alloc_unpack_tuple_t{}, _Al, _STD move(_Right)) {}
623+
#endif // _HAS_CXX23
624+
625+
#if _HAS_CXX23
626+
template <class _Alloc, class _First, class _Second,
627+
enable_if_t<_Tuple_constructible_v<tuple, _First&, _Second&>, int> = 0>
628+
constexpr explicit(_Tuple_conditional_explicit_v<tuple, _First&, _Second&>)
629+
tuple(allocator_arg_t, const _Alloc& _Al, pair<_First, _Second>& _Right)
630+
: tuple(_Alloc_unpack_tuple_t{}, _Al, _Right) {}
631+
#endif // _HAS_CXX23
632+
561633
#if _HAS_CONDITIONAL_EXPLICIT
562634
template <class _Alloc, class _First, class _Second,
563635
enable_if_t<_Tuple_constructible_v<tuple, const _First&, const _Second&>, int> = 0>
@@ -594,6 +666,14 @@ public:
594666
: tuple(_Alloc_unpack_tuple_t{}, _Al, _STD move(_Right)) {}
595667
#endif // ^^^ !_HAS_CONDITIONAL_EXPLICIT ^^^
596668

669+
#if _HAS_CXX23
670+
template <class _Alloc, class _First, class _Second,
671+
enable_if_t<_Tuple_constructible_v<tuple, const _First, const _Second>, int> = 0>
672+
constexpr explicit(_Tuple_conditional_explicit_v<tuple, const _First, const _Second>)
673+
tuple(allocator_arg_t, const _Alloc& _Al, const pair<_First, _Second>&& _Right)
674+
: tuple(_Alloc_unpack_tuple_t{}, _Al, _STD move(_Right)) {}
675+
#endif // _HAS_CXX23
676+
597677
tuple& operator=(const volatile tuple&) = delete;
598678

599679
template <class _Myself = tuple, class _This2 = _This,
@@ -607,6 +687,20 @@ public:
607687
return *this;
608688
}
609689

690+
#if _HAS_CXX23
691+
template <class _Myself = tuple, class _This2 = _This,
692+
enable_if_t<conjunction_v<_STD _Is_copy_assignable_no_precondition_check<const _This2>,
693+
_STD _Is_copy_assignable_no_precondition_check<const _Rest>...>,
694+
int> = 0>
695+
constexpr const tuple& operator=(_Identity_t<const _Myself&> _Right) const
696+
noexcept(conjunction_v<is_nothrow_copy_assignable<const _This2>,
697+
is_nothrow_copy_assignable<const _Rest>...>) /* strengthened */ {
698+
_Myfirst._Val = _Right._Myfirst._Val;
699+
_Get_rest() = _Right._Get_rest();
700+
return *this;
701+
}
702+
#endif // _HAS_CXX23
703+
610704
template <class _Myself = tuple, class _This2 = _This,
611705
enable_if_t<conjunction_v<_STD _Is_move_assignable_no_precondition_check<_This2>,
612706
_STD _Is_move_assignable_no_precondition_check<_Rest>...>,
@@ -618,6 +712,20 @@ public:
618712
return *this;
619713
}
620714

715+
#if _HAS_CXX23
716+
template <class _Myself = tuple, class _This2 = _This,
717+
enable_if_t<conjunction_v<_STD _Is_assignable_no_precondition_check<const _This2&, _This2>,
718+
_STD _Is_assignable_no_precondition_check<const _Rest&, _Rest>...>,
719+
int> = 0>
720+
constexpr const tuple& operator=(_Identity_t<_Myself&&> _Right) const
721+
noexcept(conjunction_v<is_nothrow_assignable<const _This2&, _This2>,
722+
is_nothrow_assignable<const _Rest&, _Rest>...>) /* strengthened */ {
723+
_Myfirst._Val = _STD forward<_This>(_Right._Myfirst._Val);
724+
_Get_rest() = _STD forward<_Mybase>(_Right._Get_rest());
725+
return *this;
726+
}
727+
#endif // _HAS_CXX23
728+
621729
template <class... _Other, enable_if_t<conjunction_v<_STD negation<_STD is_same<tuple, _STD tuple<_Other...>>>,
622730
_STD _Tuple_assignable_val<tuple, const _Other&...>>,
623731
int> = 0>
@@ -628,6 +736,18 @@ public:
628736
return *this;
629737
}
630738

739+
#if _HAS_CXX23
740+
template <class... _Other, enable_if_t<conjunction_v<_STD negation<_STD is_same<tuple, _STD tuple<_Other...>>>,
741+
_STD _Tuple_assignable_val<const tuple, const _Other&...>>,
742+
int> = 0>
743+
constexpr const tuple& operator=(const tuple<_Other...>& _Right) const
744+
noexcept(_Tuple_nothrow_assignable_v<const tuple, const _Other&...>) /* strengthened */ {
745+
_Myfirst._Val = _Right._Myfirst._Val;
746+
_Get_rest() = _Right._Get_rest();
747+
return *this;
748+
}
749+
#endif // _HAS_CXX23
750+
631751
template <class... _Other, enable_if_t<conjunction_v<_STD negation<_STD is_same<tuple, _STD tuple<_Other...>>>,
632752
_STD _Tuple_assignable_val<tuple, _Other...>>,
633753
int> = 0>
@@ -638,6 +758,18 @@ public:
638758
return *this;
639759
}
640760

761+
#if _HAS_CXX23
762+
template <class... _Other, enable_if_t<conjunction_v<_STD negation<_STD is_same<tuple, _STD tuple<_Other...>>>,
763+
_STD _Tuple_assignable_val<const tuple, _Other...>>,
764+
int> = 0>
765+
constexpr const tuple& operator=(tuple<_Other...>&& _Right) const
766+
noexcept(_Tuple_nothrow_assignable_v<const tuple, _Other...>) /* strengthened */ {
767+
_Myfirst._Val = _STD forward<typename tuple<_Other...>::_This_type>(_Right._Myfirst._Val);
768+
_Get_rest() = _STD forward<typename tuple<_Other...>::_Mybase>(_Right._Get_rest());
769+
return *this;
770+
}
771+
#endif // _HAS_CXX23
772+
641773
template <class _First, class _Second,
642774
enable_if_t<_Tuple_assignable_v<tuple, const _First&, const _Second&>, int> = 0>
643775
_CONSTEXPR20 tuple& operator=(const pair<_First, _Second>& _Right) noexcept(
@@ -647,6 +779,17 @@ public:
647779
return *this;
648780
}
649781

782+
#if _HAS_CXX23
783+
template <class _First, class _Second,
784+
enable_if_t<_Tuple_assignable_v<const tuple, const _First&, const _Second&>, int> = 0>
785+
constexpr const tuple& operator=(const pair<_First, _Second>& _Right) const
786+
noexcept(_Tuple_nothrow_assignable_v<const tuple, const _First&, const _Second&>) /* strengthened */ {
787+
_Myfirst._Val = _Right.first;
788+
_Get_rest()._Myfirst._Val = _Right.second;
789+
return *this;
790+
}
791+
#endif // _HAS_CXX23
792+
650793
template <class _First, class _Second, enable_if_t<_Tuple_assignable_v<tuple, _First, _Second>, int> = 0>
651794
_CONSTEXPR20 tuple& operator=(pair<_First, _Second>&& _Right) noexcept(
652795
_Tuple_nothrow_assignable_v<tuple, _First, _Second>) /* strengthened */ {
@@ -655,12 +798,30 @@ public:
655798
return *this;
656799
}
657800

801+
#if _HAS_CXX23
802+
template <class _First, class _Second, enable_if_t<_Tuple_assignable_v<const tuple, _First, _Second>, int> = 0>
803+
constexpr const tuple& operator=(pair<_First, _Second>&& _Right) const
804+
noexcept(_Tuple_nothrow_assignable_v<const tuple, _First, _Second>) /* strengthened */ {
805+
_Myfirst._Val = _STD forward<_First>(_Right.first);
806+
_Get_rest()._Myfirst._Val = _STD forward<_Second>(_Right.second);
807+
return *this;
808+
}
809+
#endif // _HAS_CXX23
810+
658811
_CONSTEXPR20 void swap(tuple& _Right) noexcept(
659812
conjunction_v<_Is_nothrow_swappable<_This>, _Is_nothrow_swappable<_Rest>...>) {
660813
_Swap_adl(_Myfirst._Val, _Right._Myfirst._Val);
661814
_Mybase::swap(_Right._Get_rest());
662815
}
663816

817+
#if _HAS_CXX23
818+
constexpr void swap(const tuple& _Right) const
819+
noexcept(conjunction_v<_Is_nothrow_swappable<const _This>, _Is_nothrow_swappable<const _Rest>...>) {
820+
_Swap_adl(_Myfirst._Val, _Right._Myfirst._Val);
821+
_Mybase::swap(_Right._Get_rest());
822+
}
823+
#endif // _HAS_CXX23
824+
664825
constexpr _Mybase& _Get_rest() noexcept { // get reference to rest of elements
665826
return *this;
666827
}
@@ -787,6 +948,14 @@ _CONSTEXPR20 void swap(tuple<_Types...>& _Left, tuple<_Types...>& _Right) noexce
787948
return _Left.swap(_Right);
788949
}
789950

951+
#if _HAS_CXX23
952+
template <class... _Types, enable_if_t<conjunction_v<_STD _Is_swappable<const _Types>...>, int> = 0>
953+
constexpr void swap(const tuple<_Types...>& _Left, const tuple<_Types...>& _Right) noexcept(
954+
noexcept(_Left.swap(_Right))) {
955+
return _Left.swap(_Right);
956+
}
957+
#endif // _HAS_CXX23
958+
790959
template <class _Ty, class _Tuple>
791960
struct _Tuple_element {}; // backstop _Tuple_element definition
792961

@@ -1003,6 +1172,24 @@ _NODISCARD constexpr _Ty make_from_tuple(_Tuple&& _Tpl) { // construct _Ty from
10031172
template <class... _Types, class _Alloc>
10041173
struct uses_allocator<tuple<_Types...>, _Alloc> : true_type {}; // true_type if container allocator enabled
10051174

1175+
#if _HAS_CXX23
1176+
template <class... _TTypes, class... _UTypes, template <class> class _TQual, template <class> class _UQual>
1177+
requires requires {
1178+
typename tuple<common_reference_t<_TQual<_TTypes>, _UQual<_UTypes>>...>;
1179+
}
1180+
struct basic_common_reference<tuple<_TTypes...>, tuple<_UTypes...>, _TQual, _UQual> {
1181+
using type = tuple<common_reference_t<_TQual<_TTypes>, _UQual<_UTypes>>...>;
1182+
};
1183+
1184+
template <class... _TTypes, class... _UTypes>
1185+
requires requires {
1186+
typename tuple<common_type_t<_TTypes, _UTypes>...>;
1187+
}
1188+
struct common_type<tuple<_TTypes...>, tuple<_UTypes...>> {
1189+
using type = tuple<common_type_t<_TTypes, _UTypes>...>;
1190+
};
1191+
#endif // _HAS_CXX23
1192+
10061193
#if _HAS_TR1_NAMESPACE
10071194
namespace _DEPRECATE_TR1_NAMESPACE tr1 {
10081195
using _STD get;

0 commit comments

Comments
 (0)