140 lines · c
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-exception7//8//===----------------------------------------------------------------------===//9 10#ifndef _LIBCPP___CXX03___MEMORY_COMPRESSED_PAIR_H11#define _LIBCPP___CXX03___MEMORY_COMPRESSED_PAIR_H12 13#include <__cxx03/__config>14#include <__cxx03/__fwd/tuple.h>15#include <__cxx03/__tuple/tuple_indices.h>16#include <__cxx03/__type_traits/decay.h>17#include <__cxx03/__type_traits/dependent_type.h>18#include <__cxx03/__type_traits/enable_if.h>19#include <__cxx03/__type_traits/is_constructible.h>20#include <__cxx03/__type_traits/is_empty.h>21#include <__cxx03/__type_traits/is_final.h>22#include <__cxx03/__type_traits/is_same.h>23#include <__cxx03/__type_traits/is_swappable.h>24#include <__cxx03/__utility/forward.h>25#include <__cxx03/__utility/move.h>26#include <__cxx03/__utility/piecewise_construct.h>27#include <__cxx03/cstddef>28 29#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)30# pragma GCC system_header31#endif32 33_LIBCPP_PUSH_MACROS34#include <__cxx03/__undef_macros>35 36_LIBCPP_BEGIN_NAMESPACE_STD37 38// Tag used to default initialize one or both of the pair's elements.39struct __default_init_tag {};40struct __value_init_tag {};41 42template <class _Tp, int _Idx, bool _CanBeEmptyBase = is_empty<_Tp>::value && !__libcpp_is_final<_Tp>::value>43struct __compressed_pair_elem {44 using _ParamT = _Tp;45 using reference = _Tp&;46 using const_reference = const _Tp&;47 48 _LIBCPP_HIDE_FROM_ABI explicit __compressed_pair_elem(__default_init_tag) {}49 _LIBCPP_HIDE_FROM_ABI explicit __compressed_pair_elem(__value_init_tag) : __value_() {}50 51 template <class _Up, __enable_if_t<!is_same<__compressed_pair_elem, __decay_t<_Up> >::value, int> = 0>52 _LIBCPP_HIDE_FROM_ABI explicit __compressed_pair_elem(_Up&& __u) : __value_(std::forward<_Up>(__u)) {}53 54 _LIBCPP_HIDE_FROM_ABI reference __get() _NOEXCEPT { return __value_; }55 _LIBCPP_HIDE_FROM_ABI const_reference __get() const _NOEXCEPT { return __value_; }56 57private:58 _Tp __value_;59};60 61template <class _Tp, int _Idx>62struct __compressed_pair_elem<_Tp, _Idx, true> : private _Tp {63 using _ParamT = _Tp;64 using reference = _Tp&;65 using const_reference = const _Tp&;66 using __value_type = _Tp;67 68 _LIBCPP_HIDE_FROM_ABI explicit __compressed_pair_elem() = default;69 _LIBCPP_HIDE_FROM_ABI explicit __compressed_pair_elem(__default_init_tag) {}70 _LIBCPP_HIDE_FROM_ABI explicit __compressed_pair_elem(__value_init_tag) : __value_type() {}71 72 template <class _Up, __enable_if_t<!is_same<__compressed_pair_elem, __decay_t<_Up> >::value, int> = 0>73 _LIBCPP_HIDE_FROM_ABI explicit __compressed_pair_elem(_Up&& __u) : __value_type(std::forward<_Up>(__u)) {}74 75 _LIBCPP_HIDE_FROM_ABI reference __get() _NOEXCEPT { return *this; }76 _LIBCPP_HIDE_FROM_ABI const_reference __get() const _NOEXCEPT { return *this; }77};78 79template <class _T1, class _T2>80class __compressed_pair : private __compressed_pair_elem<_T1, 0>, private __compressed_pair_elem<_T2, 1> {81public:82 // NOTE: This static assert should never fire because __compressed_pair83 // is *almost never* used in a scenario where it's possible for T1 == T2.84 // (The exception is std::function where it is possible that the function85 // object and the allocator have the same type).86 static_assert(87 (!is_same<_T1, _T2>::value),88 "__compressed_pair cannot be instantiated when T1 and T2 are the same type; "89 "The current implementation is NOT ABI-compatible with the previous implementation for this configuration");90 91 using _Base1 _LIBCPP_NODEBUG = __compressed_pair_elem<_T1, 0>;92 using _Base2 _LIBCPP_NODEBUG = __compressed_pair_elem<_T2, 1>;93 94 template <bool _Dummy = true,95 __enable_if_t< __dependent_type<is_default_constructible<_T1>, _Dummy>::value &&96 __dependent_type<is_default_constructible<_T2>, _Dummy>::value,97 int> = 0>98 _LIBCPP_HIDE_FROM_ABI explicit __compressed_pair() : _Base1(__value_init_tag()), _Base2(__value_init_tag()) {}99 100 template <class _U1, class _U2>101 _LIBCPP_HIDE_FROM_ABI explicit __compressed_pair(_U1&& __t1, _U2&& __t2)102 : _Base1(std::forward<_U1>(__t1)), _Base2(std::forward<_U2>(__t2)) {}103 104 _LIBCPP_HIDE_FROM_ABI typename _Base1::reference first() _NOEXCEPT { return static_cast<_Base1&>(*this).__get(); }105 106 _LIBCPP_HIDE_FROM_ABI typename _Base1::const_reference first() const _NOEXCEPT {107 return static_cast<_Base1 const&>(*this).__get();108 }109 110 _LIBCPP_HIDE_FROM_ABI typename _Base2::reference second() _NOEXCEPT { return static_cast<_Base2&>(*this).__get(); }111 112 _LIBCPP_HIDE_FROM_ABI typename _Base2::const_reference second() const _NOEXCEPT {113 return static_cast<_Base2 const&>(*this).__get();114 }115 116 _LIBCPP_HIDE_FROM_ABI static _Base1* __get_first_base(__compressed_pair* __pair) _NOEXCEPT {117 return static_cast<_Base1*>(__pair);118 }119 _LIBCPP_HIDE_FROM_ABI static _Base2* __get_second_base(__compressed_pair* __pair) _NOEXCEPT {120 return static_cast<_Base2*>(__pair);121 }122 123 _LIBCPP_HIDE_FROM_ABI void swap(__compressed_pair& __x) {124 using std::swap;125 swap(first(), __x.first());126 swap(second(), __x.second());127 }128};129 130template <class _T1, class _T2>131inline _LIBCPP_HIDE_FROM_ABI void swap(__compressed_pair<_T1, _T2>& __x, __compressed_pair<_T1, _T2>& __y) {132 __x.swap(__y);133}134 135_LIBCPP_END_NAMESPACE_STD136 137_LIBCPP_POP_MACROS138 139#endif // _LIBCPP___CXX03___MEMORY_COMPRESSED_PAIR_H140