Skip to content

Commit

Permalink
Make pair, tuple and vector<bool>::reference usable as proxy references
Browse files Browse the repository at this point in the history
  • Loading branch information
cpplearner committed Apr 28, 2022
1 parent 5a2b58f commit 7869d61
Show file tree
Hide file tree
Showing 11 changed files with 685 additions and 8 deletions.
187 changes: 187 additions & 0 deletions stl/inc/tuple
Original file line number Diff line number Diff line change
Expand Up @@ -219,8 +219,16 @@ public:
constexpr tuple(_Tag, const _Alloc&) noexcept /* strengthened */ {}

constexpr tuple& operator=(const tuple&) = default;
#if _HAS_CXX23
constexpr const tuple& operator=(const tuple&) const {
return *this;
}
#endif // _HAS_CXX23

_CONSTEXPR20 void swap(tuple&) noexcept {}
#if _HAS_CXX23
constexpr void swap(const tuple&) const noexcept {}
#endif // _HAS_CXX23

constexpr bool _Equals(const tuple&) const noexcept {
return true;
Expand Down Expand Up @@ -349,6 +357,15 @@ public:
tuple(const tuple&) = default;
tuple(tuple&&) = default;

#if _HAS_CXX23
template <class... _Other, enable_if_t<conjunction_v<_STD _Tuple_constructible_val<tuple, _Other&...>,
_STD _Tuple_convert_val<tuple, tuple<_Other...>&, _Other...>>,
int> = 0>
constexpr explicit(_Tuple_conditional_explicit_v<tuple, _Other&...>)
tuple(tuple<_Other...>& _Right) noexcept(_Tuple_nothrow_constructible_v<tuple, _Other&...>) // strengthened
: tuple(_Unpack_tuple_t{}, _Right) {}
#endif // _HAS_CXX23

#if _HAS_CONDITIONAL_EXPLICIT
template <class... _Other, enable_if_t<conjunction_v<_STD _Tuple_constructible_val<tuple, const _Other&...>,
_STD _Tuple_convert_val<tuple, const tuple<_Other...>&, _Other...>>,
Expand Down Expand Up @@ -396,6 +413,24 @@ public:
: tuple(_Unpack_tuple_t{}, _STD move(_Right)) {}
#endif // ^^^ !_HAS_CONDITIONAL_EXPLICIT ^^^

#if _HAS_CXX23
template <class... _Other, enable_if_t<conjunction_v<_STD _Tuple_constructible_val<tuple, const _Other...>,
_STD _Tuple_convert_val<tuple, const tuple<_Other...>, _Other...>>,
int> = 0>
constexpr explicit(_Tuple_conditional_explicit_v<tuple, const _Other...>)
tuple(const tuple<_Other...>&& _Right) noexcept(
_Tuple_nothrow_constructible_v<tuple, const _Other...>) // strengthened
: tuple(_Unpack_tuple_t{}, _STD move(_Right)) {}
#endif // _HAS_CXX23

#if _HAS_CXX23
template <class _First, class _Second, enable_if_t<_Tuple_constructible_v<tuple, _First&, _Second&>, int> = 0>
constexpr explicit(_Tuple_conditional_explicit_v<tuple, _First&, _Second&>)
tuple(pair<_First, _Second>& _Right) noexcept(
_Tuple_nothrow_constructible_v<tuple, _First&, _Second&>) // strengthened
: tuple(_Unpack_tuple_t{}, _Right) {}
#endif // _HAS_CXX23

#if _HAS_CONDITIONAL_EXPLICIT
template <class _First, class _Second,
enable_if_t<_Tuple_constructible_v<tuple, const _First&, const _Second&>, int> = 0>
Expand Down Expand Up @@ -434,6 +469,15 @@ public:
: tuple(_Unpack_tuple_t{}, _STD move(_Right)) {}
#endif // ^^^ !_HAS_CONDITIONAL_EXPLICIT ^^^

#if _HAS_CXX23
template <class _First, class _Second,
enable_if_t<_Tuple_constructible_v<tuple, const _First, const _Second>, int> = 0>
constexpr explicit(_Tuple_conditional_explicit_v<tuple, const _First, const _Second>)
tuple(const pair<_First, _Second>&& _Right) noexcept(
_Tuple_nothrow_constructible_v<tuple, const _First, const _Second>) // strengthened
: tuple(_Unpack_tuple_t{}, _STD move(_Right)) {}
#endif // _HAS_CXX23

#if _HAS_CONDITIONAL_EXPLICIT
template <class _Alloc, class _This2 = _This,
enable_if_t<conjunction_v<_STD is_default_constructible<_This2>, _STD is_default_constructible<_Rest>...>,
Expand Down Expand Up @@ -510,6 +554,16 @@ public:
_CONSTEXPR20 tuple(allocator_arg_t, const _Alloc& _Al, tuple&& _Right)
: tuple(_Alloc_unpack_tuple_t{}, _Al, _STD move(_Right)) {}

#if _HAS_CXX23
template <class _Alloc, class... _Other,
enable_if_t<conjunction_v<_STD _Tuple_constructible_val<tuple, _Other&...>,
_STD _Tuple_convert_val<tuple, tuple<_Other...>&, _Other...>>,
int> = 0>
constexpr explicit(_Tuple_conditional_explicit_v<tuple, _Other&...>)
tuple(allocator_arg_t, const _Alloc& _Al, tuple<_Other...>& _Right)
: tuple(_Alloc_unpack_tuple_t{}, _Al, _Right) {}
#endif // _HAS_CXX23

#if _HAS_CONDITIONAL_EXPLICIT
template <class _Alloc, class... _Other,
enable_if_t<conjunction_v<_STD _Tuple_constructible_val<tuple, const _Other&...>,
Expand Down Expand Up @@ -558,6 +612,24 @@ public:
: tuple(_Alloc_unpack_tuple_t{}, _Al, _STD move(_Right)) {}
#endif // ^^^ !_HAS_CONDITIONAL_EXPLICIT ^^^

#if _HAS_CXX23
template <class _Alloc, class... _Other,
enable_if_t<conjunction_v<_STD _Tuple_constructible_val<tuple, const _Other...>,
_STD _Tuple_convert_val<tuple, const tuple<_Other...>, _Other...>>,
int> = 0>
constexpr explicit(_Tuple_conditional_explicit_v<tuple, const _Other...>)
tuple(allocator_arg_t, const _Alloc& _Al, const tuple<_Other...>&& _Right)
: tuple(_Alloc_unpack_tuple_t{}, _Al, _STD move(_Right)) {}
#endif // _HAS_CXX23

#if _HAS_CXX23
template <class _Alloc, class _First, class _Second,
enable_if_t<_Tuple_constructible_v<tuple, _First&, _Second&>, int> = 0>
constexpr explicit(_Tuple_conditional_explicit_v<tuple, _First&, _Second&>)
tuple(allocator_arg_t, const _Alloc& _Al, pair<_First, _Second>& _Right)
: tuple(_Alloc_unpack_tuple_t{}, _Al, _Right) {}
#endif // _HAS_CXX23

#if _HAS_CONDITIONAL_EXPLICIT
template <class _Alloc, class _First, class _Second,
enable_if_t<_Tuple_constructible_v<tuple, const _First&, const _Second&>, int> = 0>
Expand Down Expand Up @@ -594,6 +666,14 @@ public:
: tuple(_Alloc_unpack_tuple_t{}, _Al, _STD move(_Right)) {}
#endif // ^^^ !_HAS_CONDITIONAL_EXPLICIT ^^^

#if _HAS_CXX23
template <class _Alloc, class _First, class _Second,
enable_if_t<_Tuple_constructible_v<tuple, const _First, const _Second>, int> = 0>
constexpr explicit(_Tuple_conditional_explicit_v<tuple, const _First, const _Second>)
tuple(allocator_arg_t, const _Alloc& _Al, const pair<_First, _Second>&& _Right)
: tuple(_Alloc_unpack_tuple_t{}, _Al, _STD move(_Right)) {}
#endif // _HAS_CXX23

tuple& operator=(const volatile tuple&) = delete;

template <class _Myself = tuple, class _This2 = _This,
Expand All @@ -607,6 +687,20 @@ public:
return *this;
}

#if _HAS_CXX23
template <class _Myself = tuple, class _This2 = _This,
enable_if_t<conjunction_v<_STD _Is_copy_assignable_no_precondition_check<const _This2>,
_STD _Is_copy_assignable_no_precondition_check<const _Rest>...>,
int> = 0>
constexpr const tuple& operator=(_Identity_t<const _Myself&> _Right) const
noexcept(conjunction_v<is_nothrow_copy_assignable<const _This2>,
is_nothrow_copy_assignable<const _Rest>...>) /* strengthened */ {
_Myfirst._Val = _Right._Myfirst._Val;
_Get_rest() = _Right._Get_rest();
return *this;
}
#endif // _HAS_CXX23

template <class _Myself = tuple, class _This2 = _This,
enable_if_t<conjunction_v<_STD _Is_move_assignable_no_precondition_check<_This2>,
_STD _Is_move_assignable_no_precondition_check<_Rest>...>,
Expand All @@ -618,6 +712,20 @@ public:
return *this;
}

#if _HAS_CXX23
template <class _Myself = tuple, class _This2 = _This,
enable_if_t<conjunction_v<_STD _Is_assignable_no_precondition_check<const _This2&, _This2>,
_STD _Is_assignable_no_precondition_check<const _Rest&, _Rest>...>,
int> = 0>
constexpr const tuple& operator=(_Identity_t<_Myself&&> _Right) const
noexcept(conjunction_v<is_nothrow_assignable<const _This2&, _This2>,
is_nothrow_assignable<const _Rest&, _Rest>...>) /* strengthened */ {
_Myfirst._Val = _STD forward<_This>(_Right._Myfirst._Val);
_Get_rest() = _STD forward<_Mybase>(_Right._Get_rest());
return *this;
}
#endif // _HAS_CXX23

template <class... _Other, enable_if_t<conjunction_v<_STD negation<_STD is_same<tuple, _STD tuple<_Other...>>>,
_STD _Tuple_assignable_val<tuple, const _Other&...>>,
int> = 0>
Expand All @@ -628,6 +736,18 @@ public:
return *this;
}

#if _HAS_CXX23
template <class... _Other, enable_if_t<conjunction_v<_STD negation<_STD is_same<tuple, _STD tuple<_Other...>>>,
_STD _Tuple_assignable_val<const tuple, const _Other&...>>,
int> = 0>
constexpr const tuple& operator=(const tuple<_Other...>& _Right) const
noexcept(_Tuple_nothrow_assignable_v<const tuple, const _Other&...>) /* strengthened */ {
_Myfirst._Val = _Right._Myfirst._Val;
_Get_rest() = _Right._Get_rest();
return *this;
}
#endif // _HAS_CXX23

template <class... _Other, enable_if_t<conjunction_v<_STD negation<_STD is_same<tuple, _STD tuple<_Other...>>>,
_STD _Tuple_assignable_val<tuple, _Other...>>,
int> = 0>
Expand All @@ -638,6 +758,18 @@ public:
return *this;
}

#if _HAS_CXX23
template <class... _Other, enable_if_t<conjunction_v<_STD negation<_STD is_same<tuple, _STD tuple<_Other...>>>,
_STD _Tuple_assignable_val<const tuple, _Other...>>,
int> = 0>
constexpr const tuple& operator=(tuple<_Other...>&& _Right) const
noexcept(_Tuple_nothrow_assignable_v<const tuple, _Other...>) /* strengthened */ {
_Myfirst._Val = _STD forward<typename tuple<_Other...>::_This_type>(_Right._Myfirst._Val);
_Get_rest() = _STD forward<typename tuple<_Other...>::_Mybase>(_Right._Get_rest());
return *this;
}
#endif // _HAS_CXX23

template <class _First, class _Second,
enable_if_t<_Tuple_assignable_v<tuple, const _First&, const _Second&>, int> = 0>
_CONSTEXPR20 tuple& operator=(const pair<_First, _Second>& _Right) noexcept(
Expand All @@ -647,6 +779,17 @@ public:
return *this;
}

#if _HAS_CXX23
template <class _First, class _Second,
enable_if_t<_Tuple_assignable_v<const tuple, const _First&, const _Second&>, int> = 0>
constexpr const tuple& operator=(const pair<_First, _Second>& _Right) const
noexcept(_Tuple_nothrow_assignable_v<const tuple, const _First&, const _Second&>) /* strengthened */ {
_Myfirst._Val = _Right.first;
_Get_rest()._Myfirst._Val = _Right.second;
return *this;
}
#endif // _HAS_CXX23

template <class _First, class _Second, enable_if_t<_Tuple_assignable_v<tuple, _First, _Second>, int> = 0>
_CONSTEXPR20 tuple& operator=(pair<_First, _Second>&& _Right) noexcept(
_Tuple_nothrow_assignable_v<tuple, _First, _Second>) /* strengthened */ {
Expand All @@ -655,12 +798,30 @@ public:
return *this;
}

#if _HAS_CXX23
template <class _First, class _Second, enable_if_t<_Tuple_assignable_v<const tuple, _First, _Second>, int> = 0>
constexpr const tuple& operator=(pair<_First, _Second>&& _Right) const
noexcept(_Tuple_nothrow_assignable_v<const tuple, _First, _Second>) /* strengthened */ {
_Myfirst._Val = _STD forward<_First>(_Right.first);
_Get_rest()._Myfirst._Val = _STD forward<_Second>(_Right.second);
return *this;
}
#endif // _HAS_CXX23

_CONSTEXPR20 void swap(tuple& _Right) noexcept(
conjunction_v<_Is_nothrow_swappable<_This>, _Is_nothrow_swappable<_Rest>...>) {
_Swap_adl(_Myfirst._Val, _Right._Myfirst._Val);
_Mybase::swap(_Right._Get_rest());
}

#if _HAS_CXX23
constexpr void swap(const tuple& _Right) const
noexcept(conjunction_v<_Is_nothrow_swappable<const _This>, _Is_nothrow_swappable<const _Rest>...>) {
_Swap_adl(_Myfirst._Val, _Right._Myfirst._Val);
_Mybase::swap(_Right._Get_rest());
}
#endif // _HAS_CXX23

constexpr _Mybase& _Get_rest() noexcept { // get reference to rest of elements
return *this;
}
Expand Down Expand Up @@ -787,6 +948,14 @@ _CONSTEXPR20 void swap(tuple<_Types...>& _Left, tuple<_Types...>& _Right) noexce
return _Left.swap(_Right);
}

#if _HAS_CXX23
template <class... _Types, enable_if_t<conjunction_v<_STD _Is_swappable<const _Types>...>, int> = 0>
constexpr void swap(const tuple<_Types...>& _Left, const tuple<_Types...>& _Right) noexcept(
noexcept(_Left.swap(_Right))) {
return _Left.swap(_Right);
}
#endif // _HAS_CXX23

template <class _Ty, class _Tuple>
struct _Tuple_element {}; // backstop _Tuple_element definition

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

#if _HAS_CXX23
template <class... _TTypes, class... _UTypes, template <class> class _TQual, template <class> class _UQual>
requires requires {
typename tuple<common_reference_t<_TQual<_TTypes>, _UQual<_UTypes>>...>;
}
struct basic_common_reference<tuple<_TTypes...>, tuple<_UTypes...>, _TQual, _UQual> {
using type = tuple<common_reference_t<_TQual<_TTypes>, _UQual<_UTypes>>...>;
};

template <class... _TTypes, class... _UTypes>
requires requires {
typename tuple<common_type_t<_TTypes, _UTypes>...>;
}
struct common_type<tuple<_TTypes...>, tuple<_UTypes...>> {
using type = tuple<common_type_t<_TTypes, _UTypes>...>;
};
#endif // _HAS_CXX23

#if _HAS_TR1_NAMESPACE
namespace _DEPRECATE_TR1_NAMESPACE tr1 {
using _STD get;
Expand Down
Loading

0 comments on commit 7869d61

Please sign in to comment.