1 // -*- C++ -*- 2 //===----------------------------------------------------------------------===// 3 // 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 7 // 8 //===----------------------------------------------------------------------===// 9 10 #ifndef _LIBCPP___MEMORY_COMPRESSED_PAIR_H 11 #define _LIBCPP___MEMORY_COMPRESSED_PAIR_H 12 13 #include <__config> 14 #include <__utility/forward.h> 15 #include <tuple> // needed in c++03 for some constructors 16 #include <type_traits> 17 #include <utility> 18 19 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 20 #pragma GCC system_header 21 #endif 22 23 _LIBCPP_BEGIN_NAMESPACE_STD 24 25 // Tag used to default initialize one or both of the pair's elements. 26 struct __default_init_tag {}; 27 struct __value_init_tag {}; 28 29 template <class _Tp, int _Idx, 30 bool _CanBeEmptyBase = 31 is_empty<_Tp>::value && !__libcpp_is_final<_Tp>::value> 32 struct __compressed_pair_elem { 33 typedef _Tp _ParamT; 34 typedef _Tp& reference; 35 typedef const _Tp& const_reference; 36 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_() {} 41 42 template <class _Up, class = typename enable_if< 43 !is_same<__compressed_pair_elem, typename decay<_Up>::type>::value 44 >::type> 45 _LIBCPP_INLINE_VISIBILITY 46 _LIBCPP_CONSTEXPR explicit 47 __compressed_pair_elem(_Up&& __u) 48 : __value_(_VSTD::forward<_Up>(__u)) 49 { 50 } 51 52 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))...) {} 59 #endif 60 61 62 _LIBCPP_INLINE_VISIBILITY reference __get() _NOEXCEPT { return __value_; } 63 _LIBCPP_INLINE_VISIBILITY 64 const_reference __get() const _NOEXCEPT { return __value_; } 65 66 private: 67 _Tp __value_; 68 }; 69 70 template <class _Tp, int _Idx> 71 struct __compressed_pair_elem<_Tp, _Idx, true> : private _Tp { 72 typedef _Tp _ParamT; 73 typedef _Tp& reference; 74 typedef const _Tp& const_reference; 75 typedef _Tp __value_type; 76 77 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR __compressed_pair_elem() = default; 78 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR 79 __compressed_pair_elem(__default_init_tag) {} 80 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR 81 __compressed_pair_elem(__value_init_tag) : __value_type() {} 82 83 template <class _Up, class = typename enable_if< 84 !is_same<__compressed_pair_elem, typename decay<_Up>::type>::value 85 >::type> 86 _LIBCPP_INLINE_VISIBILITY 87 _LIBCPP_CONSTEXPR explicit 88 __compressed_pair_elem(_Up&& __u) 89 : __value_type(_VSTD::forward<_Up>(__u)) 90 {} 91 92 #ifndef _LIBCPP_CXX03_LANG 93 template <class... _Args, size_t... _Indexes> 94 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 95 __compressed_pair_elem(piecewise_construct_t, tuple<_Args...> __args, 96 __tuple_indices<_Indexes...>) 97 : __value_type(_VSTD::forward<_Args>(_VSTD::get<_Indexes>(__args))...) {} 98 #endif 99 100 _LIBCPP_INLINE_VISIBILITY reference __get() _NOEXCEPT { return *this; } 101 _LIBCPP_INLINE_VISIBILITY 102 const_reference __get() const _NOEXCEPT { return *this; } 103 }; 104 105 template <class _T1, class _T2> 106 class __compressed_pair : private __compressed_pair_elem<_T1, 0>, 107 private __compressed_pair_elem<_T2, 1> { 108 public: 109 // NOTE: This static assert should never fire because __compressed_pair 110 // is *almost never* used in a scenario where it's possible for T1 == T2. 111 // (The exception is std::function where it is possible that the function 112 // object and the allocator have the same type). 113 static_assert((!is_same<_T1, _T2>::value), 114 "__compressed_pair cannot be instantiated when T1 and T2 are the same type; " 115 "The current implementation is NOT ABI-compatible with the previous " 116 "implementation for this configuration"); 117 118 typedef _LIBCPP_NODEBUG __compressed_pair_elem<_T1, 0> _Base1; 119 typedef _LIBCPP_NODEBUG __compressed_pair_elem<_T2, 1> _Base2; 120 121 template <bool _Dummy = true, 122 class = typename enable_if< 123 __dependent_type<is_default_constructible<_T1>, _Dummy>::value && 124 __dependent_type<is_default_constructible<_T2>, _Dummy>::value 125 >::type 126 > 127 _LIBCPP_INLINE_VISIBILITY 128 _LIBCPP_CONSTEXPR __compressed_pair() : _Base1(__value_init_tag()), _Base2(__value_init_tag()) {} 129 130 template <class _U1, class _U2> 131 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR 132 __compressed_pair(_U1&& __t1, _U2&& __t2) 133 : _Base1(_VSTD::forward<_U1>(__t1)), _Base2(_VSTD::forward<_U2>(__t2)) {} 134 135 #ifndef _LIBCPP_CXX03_LANG 136 template <class... _Args1, class... _Args2> 137 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 138 __compressed_pair(piecewise_construct_t __pc, tuple<_Args1...> __first_args, 139 tuple<_Args2...> __second_args) 140 : _Base1(__pc, _VSTD::move(__first_args), 141 typename __make_tuple_indices<sizeof...(_Args1)>::type()), 142 _Base2(__pc, _VSTD::move(__second_args), 143 typename __make_tuple_indices<sizeof...(_Args2)>::type()) {} 144 #endif 145 146 _LIBCPP_INLINE_VISIBILITY 147 typename _Base1::reference first() _NOEXCEPT { 148 return static_cast<_Base1&>(*this).__get(); 149 } 150 151 _LIBCPP_INLINE_VISIBILITY 152 typename _Base1::const_reference first() const _NOEXCEPT { 153 return static_cast<_Base1 const&>(*this).__get(); 154 } 155 156 _LIBCPP_INLINE_VISIBILITY 157 typename _Base2::reference second() _NOEXCEPT { 158 return static_cast<_Base2&>(*this).__get(); 159 } 160 161 _LIBCPP_INLINE_VISIBILITY 162 typename _Base2::const_reference second() const _NOEXCEPT { 163 return static_cast<_Base2 const&>(*this).__get(); 164 } 165 166 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR 167 static _Base1* __get_first_base(__compressed_pair* __pair) _NOEXCEPT { 168 return static_cast<_Base1*>(__pair); 169 } 170 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR 171 static _Base2* __get_second_base(__compressed_pair* __pair) _NOEXCEPT { 172 return static_cast<_Base2*>(__pair); 173 } 174 175 _LIBCPP_INLINE_VISIBILITY 176 void swap(__compressed_pair& __x) 177 _NOEXCEPT_(__is_nothrow_swappable<_T1>::value && 178 __is_nothrow_swappable<_T2>::value) 179 { 180 using _VSTD::swap; 181 swap(first(), __x.first()); 182 swap(second(), __x.second()); 183 } 184 }; 185 186 template <class _T1, class _T2> 187 inline _LIBCPP_INLINE_VISIBILITY 188 void swap(__compressed_pair<_T1, _T2>& __x, __compressed_pair<_T1, _T2>& __y) 189 _NOEXCEPT_(__is_nothrow_swappable<_T1>::value && 190 __is_nothrow_swappable<_T2>::value) { 191 __x.swap(__y); 192 } 193 194 _LIBCPP_END_NAMESPACE_STD 195 196 #endif // _LIBCPP___MEMORY_COMPRESSED_PAIR_H 197