xref: /freebsd/contrib/llvm-project/libcxx/include/__cxx03/__memory/compressed_pair.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
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___CXX03___MEMORY_COMPRESSED_PAIR_H
11 #define _LIBCPP___CXX03___MEMORY_COMPRESSED_PAIR_H
12 
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_header
31 #endif
32 
33 _LIBCPP_PUSH_MACROS
34 #include <__cxx03/__undef_macros>
35 
36 _LIBCPP_BEGIN_NAMESPACE_STD
37 
38 // Tag used to default initialize one or both of the pair's elements.
39 struct __default_init_tag {};
40 struct __value_init_tag {};
41 
42 template <class _Tp, int _Idx, bool _CanBeEmptyBase = is_empty<_Tp>::value && !__libcpp_is_final<_Tp>::value>
43 struct __compressed_pair_elem {
44   using _ParamT         = _Tp;
45   using reference       = _Tp&;
46   using const_reference = const _Tp&;
47 
__compressed_pair_elem__compressed_pair_elem48   _LIBCPP_HIDE_FROM_ABI explicit __compressed_pair_elem(__default_init_tag) {}
__compressed_pair_elem__compressed_pair_elem49   _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>
__compressed_pair_elem__compressed_pair_elem52   _LIBCPP_HIDE_FROM_ABI explicit __compressed_pair_elem(_Up&& __u) : __value_(std::forward<_Up>(__u)) {}
53 
__get__compressed_pair_elem54   _LIBCPP_HIDE_FROM_ABI reference __get() _NOEXCEPT { return __value_; }
__get__compressed_pair_elem55   _LIBCPP_HIDE_FROM_ABI const_reference __get() const _NOEXCEPT { return __value_; }
56 
57 private:
58   _Tp __value_;
59 };
60 
61 template <class _Tp, int _Idx>
62 struct __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 
79 template <class _T1, class _T2>
80 class __compressed_pair : private __compressed_pair_elem<_T1, 0>, private __compressed_pair_elem<_T2, 1> {
81 public:
82   // NOTE: This static assert should never fire because __compressed_pair
83   // 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 function
85   //  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 
130 template <class _T1, class _T2>
131 inline _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_STD
136 
137 _LIBCPP_POP_MACROS
138 
139 #endif // _LIBCPP___CXX03___MEMORY_COMPRESSED_PAIR_H
140