Built motion from commit 6a09e18b.|2.6.11
[motion2.git] / legacy-libs / grpc-cloned / deps / grpc / third_party / abseil-cpp / absl / types / internal / optional.h
1 // Copyright 2017 The Abseil Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 #ifndef ABSL_TYPES_INTERNAL_OPTIONAL_H_
16 #define ABSL_TYPES_INTERNAL_OPTIONAL_H_
17
18 #include <functional>
19 #include <new>
20 #include <type_traits>
21 #include <utility>
22
23 #include "absl/base/internal/inline_variable.h"
24 #include "absl/memory/memory.h"
25 #include "absl/meta/type_traits.h"
26 #include "absl/utility/utility.h"
27
28 // ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS
29 //
30 // Inheriting constructors is supported in GCC 4.8+, Clang 3.3+ and MSVC 2015.
31 // __cpp_inheriting_constructors is a predefined macro and a recommended way to
32 // check for this language feature, but GCC doesn't support it until 5.0 and
33 // Clang doesn't support it until 3.6.
34 // Also, MSVC 2015 has a bug: it doesn't inherit the constexpr template
35 // constructor. For example, the following code won't work on MSVC 2015 Update3:
36 // struct Base {
37 //   int t;
38 //   template <typename T>
39 //   constexpr Base(T t_) : t(t_) {}
40 // };
41 // struct Foo : Base {
42 //   using Base::Base;
43 // }
44 // constexpr Foo foo(0);  // doesn't work on MSVC 2015
45 #if defined(__clang__)
46 #if __has_feature(cxx_inheriting_constructors)
47 #define ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS 1
48 #endif
49 #elif (defined(__GNUC__) &&                                       \
50        (__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 8)) || \
51     (__cpp_inheriting_constructors >= 200802) ||                  \
52     (defined(_MSC_VER) && _MSC_VER >= 1910)
53 #define ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS 1
54 #endif
55
56 namespace absl {
57
58 // Forward declaration
59 template <typename T>
60 class optional;
61
62 namespace optional_internal {
63
64 // This tag type is used as a constructor parameter type for `nullopt_t`.
65 struct init_t {
66   explicit init_t() = default;
67 };
68
69 struct empty_struct {};
70
71 // This class stores the data in optional<T>.
72 // It is specialized based on whether T is trivially destructible.
73 // This is the specialization for non trivially destructible type.
74 template <typename T, bool unused = std::is_trivially_destructible<T>::value>
75 class optional_data_dtor_base {
76   struct dummy_type {
77     static_assert(sizeof(T) % sizeof(empty_struct) == 0, "");
78     // Use an array to avoid GCC 6 placement-new warning.
79     empty_struct data[sizeof(T) / sizeof(empty_struct)];
80   };
81
82  protected:
83   // Whether there is data or not.
84   bool engaged_;
85   // Data storage
86   union {
87     dummy_type dummy_;
88     T data_;
89   };
90
91   void destruct() noexcept {
92     if (engaged_) {
93       data_.~T();
94       engaged_ = false;
95     }
96   }
97
98   // dummy_ must be initialized for constexpr constructor.
99   constexpr optional_data_dtor_base() noexcept : engaged_(false), dummy_{{}} {}
100
101   template <typename... Args>
102   constexpr explicit optional_data_dtor_base(in_place_t, Args&&... args)
103       : engaged_(true), data_(absl::forward<Args>(args)...) {}
104
105   ~optional_data_dtor_base() { destruct(); }
106 };
107
108 // Specialization for trivially destructible type.
109 template <typename T>
110 class optional_data_dtor_base<T, true> {
111   struct dummy_type {
112     static_assert(sizeof(T) % sizeof(empty_struct) == 0, "");
113     // Use array to avoid GCC 6 placement-new warning.
114     empty_struct data[sizeof(T) / sizeof(empty_struct)];
115   };
116
117  protected:
118   // Whether there is data or not.
119   bool engaged_;
120   // Data storage
121   union {
122     dummy_type dummy_;
123     T data_;
124   };
125   void destruct() noexcept { engaged_ = false; }
126
127   // dummy_ must be initialized for constexpr constructor.
128   constexpr optional_data_dtor_base() noexcept : engaged_(false), dummy_{{}} {}
129
130   template <typename... Args>
131   constexpr explicit optional_data_dtor_base(in_place_t, Args&&... args)
132       : engaged_(true), data_(absl::forward<Args>(args)...) {}
133 };
134
135 template <typename T>
136 class optional_data_base : public optional_data_dtor_base<T> {
137  protected:
138   using base = optional_data_dtor_base<T>;
139 #ifdef ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS
140   using base::base;
141 #else
142   optional_data_base() = default;
143
144   template <typename... Args>
145   constexpr explicit optional_data_base(in_place_t t, Args&&... args)
146       : base(t, absl::forward<Args>(args)...) {}
147 #endif
148
149   template <typename... Args>
150   void construct(Args&&... args) {
151     // Use dummy_'s address to work around casting cv-qualified T* to void*.
152     ::new (static_cast<void*>(&this->dummy_)) T(std::forward<Args>(args)...);
153     this->engaged_ = true;
154   }
155
156   template <typename U>
157   void assign(U&& u) {
158     if (this->engaged_) {
159       this->data_ = std::forward<U>(u);
160     } else {
161       construct(std::forward<U>(u));
162     }
163   }
164 };
165
166 // TODO(absl-team): Add another class using
167 // std::is_trivially_move_constructible trait when available to match
168 // http://cplusplus.github.io/LWG/lwg-defects.html#2900, for types that
169 // have trivial move but nontrivial copy.
170 // Also, we should be checking is_trivially_copyable here, which is not
171 // supported now, so we use is_trivially_* traits instead.
172 template <typename T,
173           bool unused = absl::is_trivially_copy_constructible<T>::value&&
174               absl::is_trivially_copy_assignable<typename std::remove_cv<
175                   T>::type>::value&& std::is_trivially_destructible<T>::value>
176 class optional_data;
177
178 // Trivially copyable types
179 template <typename T>
180 class optional_data<T, true> : public optional_data_base<T> {
181  protected:
182 #ifdef ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS
183   using optional_data_base<T>::optional_data_base;
184 #else
185   optional_data() = default;
186
187   template <typename... Args>
188   constexpr explicit optional_data(in_place_t t, Args&&... args)
189       : optional_data_base<T>(t, absl::forward<Args>(args)...) {}
190 #endif
191 };
192
193 template <typename T>
194 class optional_data<T, false> : public optional_data_base<T> {
195  protected:
196 #ifdef ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS
197   using optional_data_base<T>::optional_data_base;
198 #else
199   template <typename... Args>
200   constexpr explicit optional_data(in_place_t t, Args&&... args)
201       : optional_data_base<T>(t, absl::forward<Args>(args)...) {}
202 #endif
203
204   optional_data() = default;
205
206   optional_data(const optional_data& rhs) : optional_data_base<T>() {
207     if (rhs.engaged_) {
208       this->construct(rhs.data_);
209     }
210   }
211
212   optional_data(optional_data&& rhs) noexcept(
213       absl::default_allocator_is_nothrow::value ||
214       std::is_nothrow_move_constructible<T>::value)
215       : optional_data_base<T>() {
216     if (rhs.engaged_) {
217       this->construct(std::move(rhs.data_));
218     }
219   }
220
221   optional_data& operator=(const optional_data& rhs) {
222     if (rhs.engaged_) {
223       this->assign(rhs.data_);
224     } else {
225       this->destruct();
226     }
227     return *this;
228   }
229
230   optional_data& operator=(optional_data&& rhs) noexcept(
231       std::is_nothrow_move_assignable<T>::value&&
232           std::is_nothrow_move_constructible<T>::value) {
233     if (rhs.engaged_) {
234       this->assign(std::move(rhs.data_));
235     } else {
236       this->destruct();
237     }
238     return *this;
239   }
240 };
241
242 // Ordered by level of restriction, from low to high.
243 // Copyable implies movable.
244 enum class copy_traits { copyable = 0, movable = 1, non_movable = 2 };
245
246 // Base class for enabling/disabling copy/move constructor.
247 template <copy_traits>
248 class optional_ctor_base;
249
250 template <>
251 class optional_ctor_base<copy_traits::copyable> {
252  public:
253   constexpr optional_ctor_base() = default;
254   optional_ctor_base(const optional_ctor_base&) = default;
255   optional_ctor_base(optional_ctor_base&&) = default;
256   optional_ctor_base& operator=(const optional_ctor_base&) = default;
257   optional_ctor_base& operator=(optional_ctor_base&&) = default;
258 };
259
260 template <>
261 class optional_ctor_base<copy_traits::movable> {
262  public:
263   constexpr optional_ctor_base() = default;
264   optional_ctor_base(const optional_ctor_base&) = delete;
265   optional_ctor_base(optional_ctor_base&&) = default;
266   optional_ctor_base& operator=(const optional_ctor_base&) = default;
267   optional_ctor_base& operator=(optional_ctor_base&&) = default;
268 };
269
270 template <>
271 class optional_ctor_base<copy_traits::non_movable> {
272  public:
273   constexpr optional_ctor_base() = default;
274   optional_ctor_base(const optional_ctor_base&) = delete;
275   optional_ctor_base(optional_ctor_base&&) = delete;
276   optional_ctor_base& operator=(const optional_ctor_base&) = default;
277   optional_ctor_base& operator=(optional_ctor_base&&) = default;
278 };
279
280 // Base class for enabling/disabling copy/move assignment.
281 template <copy_traits>
282 class optional_assign_base;
283
284 template <>
285 class optional_assign_base<copy_traits::copyable> {
286  public:
287   constexpr optional_assign_base() = default;
288   optional_assign_base(const optional_assign_base&) = default;
289   optional_assign_base(optional_assign_base&&) = default;
290   optional_assign_base& operator=(const optional_assign_base&) = default;
291   optional_assign_base& operator=(optional_assign_base&&) = default;
292 };
293
294 template <>
295 class optional_assign_base<copy_traits::movable> {
296  public:
297   constexpr optional_assign_base() = default;
298   optional_assign_base(const optional_assign_base&) = default;
299   optional_assign_base(optional_assign_base&&) = default;
300   optional_assign_base& operator=(const optional_assign_base&) = delete;
301   optional_assign_base& operator=(optional_assign_base&&) = default;
302 };
303
304 template <>
305 class optional_assign_base<copy_traits::non_movable> {
306  public:
307   constexpr optional_assign_base() = default;
308   optional_assign_base(const optional_assign_base&) = default;
309   optional_assign_base(optional_assign_base&&) = default;
310   optional_assign_base& operator=(const optional_assign_base&) = delete;
311   optional_assign_base& operator=(optional_assign_base&&) = delete;
312 };
313
314 template <typename T>
315 struct ctor_copy_traits {
316   static constexpr copy_traits traits =
317       std::is_copy_constructible<T>::value
318           ? copy_traits::copyable
319           : std::is_move_constructible<T>::value ? copy_traits::movable
320                                                  : copy_traits::non_movable;
321 };
322
323 template <typename T>
324 struct assign_copy_traits {
325   static constexpr copy_traits traits =
326       absl::is_copy_assignable<T>::value && std::is_copy_constructible<T>::value
327           ? copy_traits::copyable
328           : absl::is_move_assignable<T>::value &&
329                     std::is_move_constructible<T>::value
330                 ? copy_traits::movable
331                 : copy_traits::non_movable;
332 };
333
334 // Whether T is constructible or convertible from optional<U>.
335 template <typename T, typename U>
336 struct is_constructible_convertible_from_optional
337     : std::integral_constant<
338           bool, std::is_constructible<T, optional<U>&>::value ||
339                     std::is_constructible<T, optional<U>&&>::value ||
340                     std::is_constructible<T, const optional<U>&>::value ||
341                     std::is_constructible<T, const optional<U>&&>::value ||
342                     std::is_convertible<optional<U>&, T>::value ||
343                     std::is_convertible<optional<U>&&, T>::value ||
344                     std::is_convertible<const optional<U>&, T>::value ||
345                     std::is_convertible<const optional<U>&&, T>::value> {};
346
347 // Whether T is constructible or convertible or assignable from optional<U>.
348 template <typename T, typename U>
349 struct is_constructible_convertible_assignable_from_optional
350     : std::integral_constant<
351           bool, is_constructible_convertible_from_optional<T, U>::value ||
352                     std::is_assignable<T&, optional<U>&>::value ||
353                     std::is_assignable<T&, optional<U>&&>::value ||
354                     std::is_assignable<T&, const optional<U>&>::value ||
355                     std::is_assignable<T&, const optional<U>&&>::value> {};
356
357 // Helper function used by [optional.relops], [optional.comp_with_t],
358 // for checking whether an expression is convertible to bool.
359 bool convertible_to_bool(bool);
360
361 // Base class for std::hash<absl::optional<T>>:
362 // If std::hash<std::remove_const_t<T>> is enabled, it provides operator() to
363 // compute the hash; Otherwise, it is disabled.
364 // Reference N4659 23.14.15 [unord.hash].
365 template <typename T, typename = size_t>
366 struct optional_hash_base {
367   optional_hash_base() = delete;
368   optional_hash_base(const optional_hash_base&) = delete;
369   optional_hash_base(optional_hash_base&&) = delete;
370   optional_hash_base& operator=(const optional_hash_base&) = delete;
371   optional_hash_base& operator=(optional_hash_base&&) = delete;
372 };
373
374 template <typename T>
375 struct optional_hash_base<T, decltype(std::hash<absl::remove_const_t<T> >()(
376                                  std::declval<absl::remove_const_t<T> >()))> {
377   using argument_type = absl::optional<T>;
378   using result_type = size_t;
379   size_t operator()(const absl::optional<T>& opt) const {
380     absl::type_traits_internal::AssertHashEnabled<absl::remove_const_t<T>>();
381     if (opt) {
382       return std::hash<absl::remove_const_t<T> >()(*opt);
383     } else {
384       return static_cast<size_t>(0x297814aaad196e6dULL);
385     }
386   }
387 };
388
389 }  // namespace optional_internal
390 }  // namespace absl
391
392 #undef ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS
393
394 #endif  // ABSL_TYPES_INTERNAL_OPTIONAL_H_