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