2 //===----------------------------------------------------------------------===//
4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 // See https://llvm.org/LICENSE.txt for license information.
6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
8 //===----------------------------------------------------------------------===//
10 #ifndef _LIBCPP___MEMORY_COMPRESSED_PAIR_H
11 #define _LIBCPP___MEMORY_COMPRESSED_PAIR_H
14 #include <__utility/forward.h>
15 #include <tuple> // needed in c++03 for some constructors
16 #include <type_traits>
19 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
20 #pragma GCC system_header
23 _LIBCPP_BEGIN_NAMESPACE_STD
25 // Tag used to default initialize one or both of the pair's elements.
26 struct __default_init_tag
{};
27 struct __value_init_tag
{};
29 template <class _Tp
, int _Idx
,
30 bool _CanBeEmptyBase
=
31 is_empty
<_Tp
>::value
&& !__libcpp_is_final
<_Tp
>::value
>
32 struct __compressed_pair_elem
{
34 typedef _Tp
& reference
;
35 typedef const _Tp
& const_reference
;
37 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
38 __compressed_pair_elem(__default_init_tag
) {}
39 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
40 __compressed_pair_elem(__value_init_tag
) : __value_() {}
42 template <class _Up
, class = typename enable_if
<
43 !is_same
<__compressed_pair_elem
, typename decay
<_Up
>::type
>::value
45 _LIBCPP_INLINE_VISIBILITY
46 _LIBCPP_CONSTEXPR
explicit
47 __compressed_pair_elem(_Up
&& __u
)
48 : __value_(_VSTD::forward
<_Up
>(__u
))
53 #ifndef _LIBCPP_CXX03_LANG
54 template <class... _Args
, size_t... _Indexes
>
55 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
56 __compressed_pair_elem(piecewise_construct_t
, tuple
<_Args
...> __args
,
57 __tuple_indices
<_Indexes
...>)
58 : __value_(_VSTD::forward
<_Args
>(_VSTD::get
<_Indexes
>(__args
))...) {}
61 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 reference
__get() _NOEXCEPT
{ return __value_
; }
62 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR const_reference
__get() const _NOEXCEPT
{ return __value_
; }
68 template <class _Tp
, int _Idx
>
69 struct __compressed_pair_elem
<_Tp
, _Idx
, true> : private _Tp
{
71 typedef _Tp
& reference
;
72 typedef const _Tp
& const_reference
;
73 typedef _Tp __value_type
;
75 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
__compressed_pair_elem() = default;
76 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
77 __compressed_pair_elem(__default_init_tag
) {}
78 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
79 __compressed_pair_elem(__value_init_tag
) : __value_type() {}
81 template <class _Up
, class = typename enable_if
<
82 !is_same
<__compressed_pair_elem
, typename decay
<_Up
>::type
>::value
84 _LIBCPP_INLINE_VISIBILITY
85 _LIBCPP_CONSTEXPR
explicit
86 __compressed_pair_elem(_Up
&& __u
)
87 : __value_type(_VSTD::forward
<_Up
>(__u
))
90 #ifndef _LIBCPP_CXX03_LANG
91 template <class... _Args
, size_t... _Indexes
>
92 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
93 __compressed_pair_elem(piecewise_construct_t
, tuple
<_Args
...> __args
,
94 __tuple_indices
<_Indexes
...>)
95 : __value_type(_VSTD::forward
<_Args
>(_VSTD::get
<_Indexes
>(__args
))...) {}
98 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 reference
__get() _NOEXCEPT
{ return *this; }
99 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR const_reference
__get() const _NOEXCEPT
{ return *this; }
102 template <class _T1
, class _T2
>
103 class __compressed_pair
: private __compressed_pair_elem
<_T1
, 0>,
104 private __compressed_pair_elem
<_T2
, 1> {
106 // NOTE: This static assert should never fire because __compressed_pair
107 // is *almost never* used in a scenario where it's possible for T1 == T2.
108 // (The exception is std::function where it is possible that the function
109 // object and the allocator have the same type).
110 static_assert((!is_same
<_T1
, _T2
>::value
),
111 "__compressed_pair cannot be instantiated when T1 and T2 are the same type; "
112 "The current implementation is NOT ABI-compatible with the previous "
113 "implementation for this configuration");
115 typedef _LIBCPP_NODEBUG __compressed_pair_elem
<_T1
, 0> _Base1
;
116 typedef _LIBCPP_NODEBUG __compressed_pair_elem
<_T2
, 1> _Base2
;
118 template <bool _Dummy
= true,
119 class = typename enable_if
<
120 __dependent_type
<is_default_constructible
<_T1
>, _Dummy
>::value
&&
121 __dependent_type
<is_default_constructible
<_T2
>, _Dummy
>::value
124 _LIBCPP_INLINE_VISIBILITY
125 _LIBCPP_CONSTEXPR
__compressed_pair() : _Base1(__value_init_tag()), _Base2(__value_init_tag()) {}
127 template <class _U1
, class _U2
>
128 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
129 __compressed_pair(_U1
&& __t1
, _U2
&& __t2
)
130 : _Base1(_VSTD::forward
<_U1
>(__t1
)), _Base2(_VSTD::forward
<_U2
>(__t2
)) {}
132 #ifndef _LIBCPP_CXX03_LANG
133 template <class... _Args1
, class... _Args2
>
134 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
135 __compressed_pair(piecewise_construct_t __pc
, tuple
<_Args1
...> __first_args
,
136 tuple
<_Args2
...> __second_args
)
137 : _Base1(__pc
, _VSTD::move(__first_args
),
138 typename __make_tuple_indices
<sizeof...(_Args1
)>::type()),
139 _Base2(__pc
, _VSTD::move(__second_args
),
140 typename __make_tuple_indices
<sizeof...(_Args2
)>::type()) {}
143 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 typename
_Base1::reference
first() _NOEXCEPT
{
144 return static_cast<_Base1
&>(*this).__get();
147 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR typename
_Base1::const_reference
first() const _NOEXCEPT
{
148 return static_cast<_Base1
const&>(*this).__get();
151 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 typename
_Base2::reference
second() _NOEXCEPT
{
152 return static_cast<_Base2
&>(*this).__get();
155 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR typename
_Base2::const_reference
second() const _NOEXCEPT
{
156 return static_cast<_Base2
const&>(*this).__get();
159 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
160 static _Base1
* __get_first_base(__compressed_pair
* __pair
) _NOEXCEPT
{
161 return static_cast<_Base1
*>(__pair
);
163 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
164 static _Base2
* __get_second_base(__compressed_pair
* __pair
) _NOEXCEPT
{
165 return static_cast<_Base2
*>(__pair
);
168 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
void swap(__compressed_pair
& __x
)
169 _NOEXCEPT_(__is_nothrow_swappable
<_T1
>::value
&& __is_nothrow_swappable
<_T2
>::value
) {
171 swap(first(), __x
.first());
172 swap(second(), __x
.second());
176 template <class _T1
, class _T2
>
177 inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
178 void swap(__compressed_pair
<_T1
, _T2
>& __x
, __compressed_pair
<_T1
, _T2
>& __y
)
179 _NOEXCEPT_(__is_nothrow_swappable
<_T1
>::value
&& __is_nothrow_swappable
<_T2
>::value
) {
183 _LIBCPP_END_NAMESPACE_STD
185 #endif // _LIBCPP___MEMORY_COMPRESSED_PAIR_H