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 _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_; } 63 64 private: 65 _Tp __value_; 66 }; 67 68 template <class _Tp, int _Idx> 69 struct __compressed_pair_elem<_Tp, _Idx, true> : private _Tp { 70 typedef _Tp _ParamT; 71 typedef _Tp& reference; 72 typedef const _Tp& const_reference; 73 typedef _Tp __value_type; 74 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() {} 80 81 template <class _Up, class = typename enable_if< 82 !is_same<__compressed_pair_elem, typename decay<_Up>::type>::value 83 >::type> 84 _LIBCPP_INLINE_VISIBILITY 85 _LIBCPP_CONSTEXPR explicit 86 __compressed_pair_elem(_Up&& __u) 87 : __value_type(_VSTD::forward<_Up>(__u)) 88 {} 89 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))...) {} 96 #endif 97 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; } 100 }; 101 102 template <class _T1, class _T2> 103 class __compressed_pair : private __compressed_pair_elem<_T1, 0>, 104 private __compressed_pair_elem<_T2, 1> { 105 public: 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"); 114 115 typedef _LIBCPP_NODEBUG __compressed_pair_elem<_T1, 0> _Base1; 116 typedef _LIBCPP_NODEBUG __compressed_pair_elem<_T2, 1> _Base2; 117 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 122 >::type 123 > 124 _LIBCPP_INLINE_VISIBILITY 125 _LIBCPP_CONSTEXPR __compressed_pair() : _Base1(__value_init_tag()), _Base2(__value_init_tag()) {} 126 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)) {} 131 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()) {} 141 #endif 142 143 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 typename _Base1::reference first() _NOEXCEPT { 144 return static_cast<_Base1&>(*this).__get(); 145 } 146 147 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR typename _Base1::const_reference first() const _NOEXCEPT { 148 return static_cast<_Base1 const&>(*this).__get(); 149 } 150 151 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 typename _Base2::reference second() _NOEXCEPT { 152 return static_cast<_Base2&>(*this).__get(); 153 } 154 155 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR typename _Base2::const_reference second() const _NOEXCEPT { 156 return static_cast<_Base2 const&>(*this).__get(); 157 } 158 159 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR 160 static _Base1* __get_first_base(__compressed_pair* __pair) _NOEXCEPT { 161 return static_cast<_Base1*>(__pair); 162 } 163 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR 164 static _Base2* __get_second_base(__compressed_pair* __pair) _NOEXCEPT { 165 return static_cast<_Base2*>(__pair); 166 } 167 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) { 170 using _VSTD::swap; 171 swap(first(), __x.first()); 172 swap(second(), __x.second()); 173 } 174 }; 175 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) { 180 __x.swap(__y); 181 } 182 183 _LIBCPP_END_NAMESPACE_STD 184 185 #endif // _LIBCPP___MEMORY_COMPRESSED_PAIR_H 186