type_traits.h
Go to the documentation of this file.
1 //
2 // Copyright 2017 The Abseil Authors.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // https://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 // -----------------------------------------------------------------------------
17 // type_traits.h
18 // -----------------------------------------------------------------------------
19 //
20 // This file contains C++11-compatible versions of standard <type_traits> API
21 // functions for determining the characteristics of types. Such traits can
22 // support type inference, classification, and transformation, as well as
23 // make it easier to write templates based on generic type behavior.
24 //
25 // See https://en.cppreference.com/w/cpp/header/type_traits
26 //
27 // WARNING: use of many of the constructs in this header will count as "complex
28 // template metaprogramming", so before proceeding, please carefully consider
29 // https://google.github.io/styleguide/cppguide.html#Template_metaprogramming
30 //
31 // WARNING: using template metaprogramming to detect or depend on API
32 // features is brittle and not guaranteed. Neither the standard library nor
33 // Abseil provides any guarantee that APIs are stable in the face of template
34 // metaprogramming. Use with caution.
35 #ifndef ABSL_META_TYPE_TRAITS_H_
36 #define ABSL_META_TYPE_TRAITS_H_
37 
38 #include <stddef.h>
39 #include <functional>
40 #include <type_traits>
41 
42 #include "absl/base/config.h"
43 
44 namespace absl {
45 
46 // Defined and documented later on in this file.
47 template <typename T>
49 
50 namespace type_traits_internal {
51 
52 // Silence MSVC warnings about the destructor being defined as deleted.
53 #if defined(_MSC_VER) && !defined(__GNUC__)
54 #pragma warning(push)
55 #pragma warning(disable : 4624)
56 #endif // defined(_MSC_VER) && !defined(__GNUC__)
57 
58 template <class T>
60  T t;
61 };
62 
63 // Restore the state of the destructor warning that was silenced above.
64 #if defined(_MSC_VER) && !defined(__GNUC__)
65 #pragma warning(pop)
66 #endif // defined(_MSC_VER) && !defined(__GNUC__)
67 
68 template <class T>
69 struct IsTriviallyMoveAssignableReference : std::false_type {};
70 
71 template <class T>
74 
75 template <class T>
78 
79 template <typename... Ts>
80 struct VoidTImpl {
81  using type = void;
82 };
83 
84 // This trick to retrieve a default alignment is necessary for our
85 // implementation of aligned_storage_t to be consistent with any implementation
86 // of std::aligned_storage.
87 template <size_t Len, typename T = std::aligned_storage<Len>>
89 
90 template <size_t Len, size_t Align>
92  std::aligned_storage<Len, Align>> {
93  static constexpr size_t value = Align;
94 };
95 
97 // Library Fundamentals V2 TS //
99 
100 // NOTE: The `is_detected` family of templates here differ from the library
101 // fundamentals specification in that for library fundamentals, `Op<Args...>` is
102 // evaluated as soon as the type `is_detected<Op, Args...>` undergoes
103 // substitution, regardless of whether or not the `::value` is accessed. That
104 // is inconsistent with all other standard traits and prevents lazy evaluation
105 // in larger contexts (such as if the `is_detected` check is a trailing argument
106 // of a `conjunction`. This implementation opts to instead be lazy in the same
107 // way that the standard traits are (this "defect" of the detection idiom
108 // specifications has been reported).
109 
110 template <class Enabler, template <class...> class Op, class... Args>
112  using type = std::false_type;
113 };
114 
115 template <template <class...> class Op, class... Args>
116 struct is_detected_impl<typename VoidTImpl<Op<Args...>>::type, Op, Args...> {
117  using type = std::true_type;
118 };
119 
120 template <template <class...> class Op, class... Args>
121 struct is_detected : is_detected_impl<void, Op, Args...>::type {};
122 
123 template <class Enabler, class To, template <class...> class Op, class... Args>
125  using type = std::false_type;
126 };
127 
128 template <class To, template <class...> class Op, class... Args>
130  typename std::enable_if<std::is_convertible<Op<Args...>, To>::value>::type,
131  To, Op, Args...> {
132  using type = std::true_type;
133 };
134 
135 template <class To, template <class...> class Op, class... Args>
137  : is_detected_convertible_impl<void, To, Op, Args...>::type {};
138 
139 template <typename T>
140 using IsCopyAssignableImpl =
141  decltype(std::declval<T&>() = std::declval<const T&>());
142 
143 template <typename T>
144 using IsMoveAssignableImpl = decltype(std::declval<T&>() = std::declval<T&&>());
145 
146 } // namespace type_traits_internal
147 
148 template <typename T>
150  type_traits_internal::IsCopyAssignableImpl, T> {
151 };
152 
153 template <typename T>
155  type_traits_internal::IsMoveAssignableImpl, T> {
156 };
157 
158 // void_t()
159 //
160 // Ignores the type of any its arguments and returns `void`. In general, this
161 // metafunction allows you to create a general case that maps to `void` while
162 // allowing specializations that map to specific types.
163 //
164 // This metafunction is designed to be a drop-in replacement for the C++17
165 // `std::void_t` metafunction.
166 //
167 // NOTE: `absl::void_t` does not use the standard-specified implementation so
168 // that it can remain compatible with gcc < 5.1. This can introduce slightly
169 // different behavior, such as when ordering partial specializations.
170 template <typename... Ts>
171 using void_t = typename type_traits_internal::VoidTImpl<Ts...>::type;
172 
173 // conjunction
174 //
175 // Performs a compile-time logical AND operation on the passed types (which
176 // must have `::value` members convertible to `bool`. Short-circuits if it
177 // encounters any `false` members (and does not compare the `::value` members
178 // of any remaining arguments).
179 //
180 // This metafunction is designed to be a drop-in replacement for the C++17
181 // `std::conjunction` metafunction.
182 template <typename... Ts>
183 struct conjunction;
184 
185 template <typename T, typename... Ts>
186 struct conjunction<T, Ts...>
187  : std::conditional<T::value, conjunction<Ts...>, T>::type {};
188 
189 template <typename T>
190 struct conjunction<T> : T {};
191 
192 template <>
193 struct conjunction<> : std::true_type {};
194 
195 // disjunction
196 //
197 // Performs a compile-time logical OR operation on the passed types (which
198 // must have `::value` members convertible to `bool`. Short-circuits if it
199 // encounters any `true` members (and does not compare the `::value` members
200 // of any remaining arguments).
201 //
202 // This metafunction is designed to be a drop-in replacement for the C++17
203 // `std::disjunction` metafunction.
204 template <typename... Ts>
205 struct disjunction;
206 
207 template <typename T, typename... Ts>
208 struct disjunction<T, Ts...> :
209  std::conditional<T::value, T, disjunction<Ts...>>::type {};
210 
211 template <typename T>
212 struct disjunction<T> : T {};
213 
214 template <>
215 struct disjunction<> : std::false_type {};
216 
217 // negation
218 //
219 // Performs a compile-time logical NOT operation on the passed type (which
220 // must have `::value` members convertible to `bool`.
221 //
222 // This metafunction is designed to be a drop-in replacement for the C++17
223 // `std::negation` metafunction.
224 template <typename T>
225 struct negation : std::integral_constant<bool, !T::value> {};
226 
227 // is_trivially_destructible()
228 //
229 // Determines whether the passed type `T` is trivially destructable.
230 //
231 // This metafunction is designed to be a drop-in replacement for the C++11
232 // `std::is_trivially_destructible()` metafunction for platforms that have
233 // incomplete C++11 support (such as libstdc++ 4.x). On any platforms that do
234 // fully support C++11, we check whether this yields the same result as the std
235 // implementation.
236 //
237 // NOTE: the extensions (__has_trivial_xxx) are implemented in gcc (version >=
238 // 4.3) and clang. Since we are supporting libstdc++ > 4.7, they should always
239 // be present. These extensions are documented at
240 // https://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html#Type-Traits.
241 template <typename T>
243  : std::integral_constant<bool, __has_trivial_destructor(T) &&
244  std::is_destructible<T>::value> {
245 #ifdef ABSL_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE
246  private:
247  static constexpr bool compliant = std::is_trivially_destructible<T>::value ==
249  static_assert(compliant || std::is_trivially_destructible<T>::value,
250  "Not compliant with std::is_trivially_destructible; "
251  "Standard: false, Implementation: true");
252  static_assert(compliant || !std::is_trivially_destructible<T>::value,
253  "Not compliant with std::is_trivially_destructible; "
254  "Standard: true, Implementation: false");
255 #endif // ABSL_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE
256 };
257 
258 // is_trivially_default_constructible()
259 //
260 // Determines whether the passed type `T` is trivially default constructible.
261 //
262 // This metafunction is designed to be a drop-in replacement for the C++11
263 // `std::is_trivially_default_constructible()` metafunction for platforms that
264 // have incomplete C++11 support (such as libstdc++ 4.x). On any platforms that
265 // do fully support C++11, we check whether this yields the same result as the
266 // std implementation.
267 //
268 // NOTE: according to the C++ standard, Section: 20.15.4.3 [meta.unary.prop]
269 // "The predicate condition for a template specialization is_constructible<T,
270 // Args...> shall be satisfied if and only if the following variable
271 // definition would be well-formed for some invented variable t:
272 //
273 // T t(declval<Args>()...);
274 //
275 // is_trivially_constructible<T, Args...> additionally requires that the
276 // variable definition does not call any operation that is not trivial.
277 // For the purposes of this check, the call to std::declval is considered
278 // trivial."
279 //
280 // Notes from https://en.cppreference.com/w/cpp/types/is_constructible:
281 // In many implementations, is_nothrow_constructible also checks if the
282 // destructor throws because it is effectively noexcept(T(arg)). Same
283 // applies to is_trivially_constructible, which, in these implementations, also
284 // requires that the destructor is trivial.
285 // GCC bug 51452: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51452
286 // LWG issue 2116: http://cplusplus.github.io/LWG/lwg-active.html#2116.
287 //
288 // "T obj();" need to be well-formed and not call any nontrivial operation.
289 // Nontrivially destructible types will cause the expression to be nontrivial.
290 template <typename T>
292  : std::integral_constant<bool, __has_trivial_constructor(T) &&
293  std::is_default_constructible<T>::value &&
294  is_trivially_destructible<T>::value> {
295 #ifdef ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE
296  private:
297  static constexpr bool compliant =
300  static_assert(compliant || std::is_trivially_default_constructible<T>::value,
301  "Not compliant with std::is_trivially_default_constructible; "
302  "Standard: false, Implementation: true");
303  static_assert(compliant || !std::is_trivially_default_constructible<T>::value,
304  "Not compliant with std::is_trivially_default_constructible; "
305  "Standard: true, Implementation: false");
306 #endif // ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE
307 };
308 
309 // is_trivially_move_constructible()
310 //
311 // Determines whether the passed type `T` is trivially move constructible.
312 //
313 // This metafunction is designed to be a drop-in replacement for the C++11
314 // `std::is_trivially_move_constructible()` metafunction for platforms that have
315 // incomplete C++11 support (such as libstdc++ 4.x). On any platforms that do
316 // fully support C++11, we check whether this yields the same result as the std
317 // implementation.
318 //
319 // NOTE: `T obj(declval<T>());` needs to be well-formed and not call any
320 // nontrivial operation. Nontrivially destructible types will cause the
321 // expression to be nontrivial.
322 template <typename T>
324  : std::conditional<
325  std::is_object<T>::value && !std::is_array<T>::value,
326  std::is_move_constructible<
327  type_traits_internal::SingleMemberUnion<T>>,
328  std::is_reference<T>>::type::type {
329 #ifdef ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE
330  private:
331  static constexpr bool compliant =
334  static_assert(compliant || std::is_trivially_move_constructible<T>::value,
335  "Not compliant with std::is_trivially_move_constructible; "
336  "Standard: false, Implementation: true");
337  static_assert(compliant || !std::is_trivially_move_constructible<T>::value,
338  "Not compliant with std::is_trivially_move_constructible; "
339  "Standard: true, Implementation: false");
340 #endif // ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE
341 };
342 
343 // is_trivially_copy_constructible()
344 //
345 // Determines whether the passed type `T` is trivially copy constructible.
346 //
347 // This metafunction is designed to be a drop-in replacement for the C++11
348 // `std::is_trivially_copy_constructible()` metafunction for platforms that have
349 // incomplete C++11 support (such as libstdc++ 4.x). On any platforms that do
350 // fully support C++11, we check whether this yields the same result as the std
351 // implementation.
352 //
353 // NOTE: `T obj(declval<const T&>());` needs to be well-formed and not call any
354 // nontrivial operation. Nontrivially destructible types will cause the
355 // expression to be nontrivial.
356 template <typename T>
358  : std::conditional<
359  std::is_object<T>::value && !std::is_array<T>::value,
360  std::is_copy_constructible<
361  type_traits_internal::SingleMemberUnion<T>>,
362  std::is_lvalue_reference<T>>::type::type {
363 #ifdef ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE
364  private:
365  static constexpr bool compliant =
368  static_assert(compliant || std::is_trivially_copy_constructible<T>::value,
369  "Not compliant with std::is_trivially_copy_constructible; "
370  "Standard: false, Implementation: true");
371  static_assert(compliant || !std::is_trivially_copy_constructible<T>::value,
372  "Not compliant with std::is_trivially_copy_constructible; "
373  "Standard: true, Implementation: false");
374 #endif // ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE
375 };
376 
377 // is_trivially_move_assignable()
378 //
379 // Determines whether the passed type `T` is trivially move assignable.
380 //
381 // This metafunction is designed to be a drop-in replacement for the C++11
382 // `std::is_trivially_move_assignable()` metafunction for platforms that have
383 // incomplete C++11 support (such as libstdc++ 4.x). On any platforms that do
384 // fully support C++11, we check whether this yields the same result as the std
385 // implementation.
386 //
387 // NOTE: `is_assignable<T, U>::value` is `true` if the expression
388 // `declval<T>() = declval<U>()` is well-formed when treated as an unevaluated
389 // operand. `is_trivially_assignable<T, U>` requires the assignment to call no
390 // operation that is not trivial. `is_trivially_copy_assignable<T>` is simply
391 // `is_trivially_assignable<T&, T>`.
392 template <typename T>
394  : std::conditional<
395  std::is_object<T>::value && !std::is_array<T>::value,
396  std::is_move_assignable<type_traits_internal::SingleMemberUnion<T>>,
397  type_traits_internal::IsTriviallyMoveAssignableReference<T>>::type::
398  type {
399 #ifdef ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE
400  private:
401  static constexpr bool compliant =
404  static_assert(compliant || std::is_trivially_move_assignable<T>::value,
405  "Not compliant with std::is_trivially_move_assignable; "
406  "Standard: false, Implementation: true");
407  static_assert(compliant || !std::is_trivially_move_assignable<T>::value,
408  "Not compliant with std::is_trivially_move_assignable; "
409  "Standard: true, Implementation: false");
410 #endif // ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE
411 };
412 
413 // is_trivially_copy_assignable()
414 //
415 // Determines whether the passed type `T` is trivially copy assignable.
416 //
417 // This metafunction is designed to be a drop-in replacement for the C++11
418 // `std::is_trivially_copy_assignable()` metafunction for platforms that have
419 // incomplete C++11 support (such as libstdc++ 4.x). On any platforms that do
420 // fully support C++11, we check whether this yields the same result as the std
421 // implementation.
422 //
423 // NOTE: `is_assignable<T, U>::value` is `true` if the expression
424 // `declval<T>() = declval<U>()` is well-formed when treated as an unevaluated
425 // operand. `is_trivially_assignable<T, U>` requires the assignment to call no
426 // operation that is not trivial. `is_trivially_copy_assignable<T>` is simply
427 // `is_trivially_assignable<T&, const T&>`.
428 template <typename T>
430  : std::integral_constant<
431  bool, __has_trivial_assign(typename std::remove_reference<T>::type) &&
432  absl::is_copy_assignable<T>::value> {
433 #ifdef ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE
434  private:
435  static constexpr bool compliant =
438  static_assert(compliant || std::is_trivially_copy_assignable<T>::value,
439  "Not compliant with std::is_trivially_copy_assignable; "
440  "Standard: false, Implementation: true");
441  static_assert(compliant || !std::is_trivially_copy_assignable<T>::value,
442  "Not compliant with std::is_trivially_copy_assignable; "
443  "Standard: true, Implementation: false");
444 #endif // ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE
445 };
446 
447 namespace type_traits_internal {
448 // is_trivially_copyable()
449 //
450 // Determines whether the passed type `T` is trivially copyable.
451 //
452 // This metafunction is designed to be a drop-in replacement for the C++11
453 // `std::is_trivially_copyable()` metafunction for platforms that have
454 // incomplete C++11 support (such as libstdc++ 4.x). We use the C++17 definition
455 // of TriviallyCopyable.
456 //
457 // NOTE: `is_trivially_copyable<T>::value` is `true` if all of T's copy/move
458 // constructors/assignment operators are trivial or deleted, T has at least
459 // one non-deleted copy/move constructor/assignment operator, and T is trivially
460 // destructible. Arrays of trivially copyable types are trivially copyable.
461 //
462 // We expose this metafunction only for internal use within absl.
463 template <typename T>
465  using ExtentsRemoved = typename std::remove_all_extents<T>::type;
466  static constexpr bool kIsCopyOrMoveConstructible =
469  static constexpr bool kIsCopyOrMoveAssignable =
472 
473  public:
474  static constexpr bool kValue =
475  (__has_trivial_copy(ExtentsRemoved) || !kIsCopyOrMoveConstructible) &&
476  (__has_trivial_assign(ExtentsRemoved) || !kIsCopyOrMoveAssignable) &&
477  (kIsCopyOrMoveConstructible || kIsCopyOrMoveAssignable) &&
479  // We need to check for this explicitly because otherwise we'll say
480  // references are trivial copyable when compiled by MSVC.
482 };
483 
484 template <typename T>
486  : std::integral_constant<
487  bool, type_traits_internal::is_trivially_copyable_impl<T>::kValue> {};
488 } // namespace type_traits_internal
489 
490 // -----------------------------------------------------------------------------
491 // C++14 "_t" trait aliases
492 // -----------------------------------------------------------------------------
493 
494 template <typename T>
495 using remove_cv_t = typename std::remove_cv<T>::type;
496 
497 template <typename T>
498 using remove_const_t = typename std::remove_const<T>::type;
499 
500 template <typename T>
501 using remove_volatile_t = typename std::remove_volatile<T>::type;
502 
503 template <typename T>
504 using add_cv_t = typename std::add_cv<T>::type;
505 
506 template <typename T>
507 using add_const_t = typename std::add_const<T>::type;
508 
509 template <typename T>
510 using add_volatile_t = typename std::add_volatile<T>::type;
511 
512 template <typename T>
513 using remove_reference_t = typename std::remove_reference<T>::type;
514 
515 template <typename T>
516 using add_lvalue_reference_t = typename std::add_lvalue_reference<T>::type;
517 
518 template <typename T>
519 using add_rvalue_reference_t = typename std::add_rvalue_reference<T>::type;
520 
521 template <typename T>
522 using remove_pointer_t = typename std::remove_pointer<T>::type;
523 
524 template <typename T>
525 using add_pointer_t = typename std::add_pointer<T>::type;
526 
527 template <typename T>
528 using make_signed_t = typename std::make_signed<T>::type;
529 
530 template <typename T>
531 using make_unsigned_t = typename std::make_unsigned<T>::type;
532 
533 template <typename T>
534 using remove_extent_t = typename std::remove_extent<T>::type;
535 
536 template <typename T>
537 using remove_all_extents_t = typename std::remove_all_extents<T>::type;
538 
539 template <size_t Len, size_t Align = type_traits_internal::
541 using aligned_storage_t = typename std::aligned_storage<Len, Align>::type;
542 
543 template <typename T>
544 using decay_t = typename std::decay<T>::type;
545 
546 template <bool B, typename T = void>
547 using enable_if_t = typename std::enable_if<B, T>::type;
548 
549 template <bool B, typename T, typename F>
550 using conditional_t = typename std::conditional<B, T, F>::type;
551 
552 template <typename... T>
553 using common_type_t = typename std::common_type<T...>::type;
554 
555 template <typename T>
556 using underlying_type_t = typename std::underlying_type<T>::type;
557 
558 template <typename T>
559 using result_of_t = typename std::result_of<T>::type;
560 
561 namespace type_traits_internal {
562 // In MSVC we can't probe std::hash or stdext::hash because it triggers a
563 // static_assert instead of failing substitution. Libc++ prior to 4.0
564 // also used a static_assert.
565 //
566 #if defined(_MSC_VER) || (defined(_LIBCPP_VERSION) && \
567  _LIBCPP_VERSION < 4000 && _LIBCPP_STD_VER > 11)
568 #define ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_ 0
569 #else
570 #define ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_ 1
571 #endif
572 
573 #if !ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
574 template <typename Key, typename = size_t>
575 struct IsHashable : std::true_type {};
576 #else // ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
577 template <typename Key, typename = void>
578 struct IsHashable : std::false_type {};
579 
580 template <typename Key>
581 struct IsHashable<
582  Key,
583  absl::enable_if_t<std::is_convertible<
584  decltype(std::declval<std::hash<Key>&>()(std::declval<Key const&>())),
585  std::size_t>::value>> : std::true_type {};
586 #endif // !ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
587 
589  private:
590  static void Sink(...) {}
591  struct NAT {};
592 
593  template <class Key>
594  static auto GetReturnType(int)
595  -> decltype(std::declval<std::hash<Key>>()(std::declval<Key const&>()));
596  template <class Key>
597  static NAT GetReturnType(...);
598 
599  template <class Key>
600  static std::nullptr_t DoIt() {
601  static_assert(IsHashable<Key>::value,
602  "std::hash<Key> does not provide a call operator");
603  static_assert(
604  std::is_default_constructible<std::hash<Key>>::value,
605  "std::hash<Key> must be default constructible when it is enabled");
606  static_assert(
607  std::is_copy_constructible<std::hash<Key>>::value,
608  "std::hash<Key> must be copy constructible when it is enabled");
609  static_assert(absl::is_copy_assignable<std::hash<Key>>::value,
610  "std::hash<Key> must be copy assignable when it is enabled");
611  // is_destructible is unchecked as it's implied by each of the
612  // is_constructible checks.
613  using ReturnType = decltype(GetReturnType<Key>(0));
614  static_assert(std::is_same<ReturnType, NAT>::value ||
616  "std::hash<Key> must return size_t");
617  return nullptr;
618  }
619 
620  template <class... Ts>
621  friend void AssertHashEnabled();
622 };
623 
624 template <class... Ts>
625 inline void AssertHashEnabled() {
626  using Helper = AssertHashEnabledHelper;
627  Helper::Sink(Helper::DoIt<Ts>()...);
628 }
629 
630 } // namespace type_traits_internal
631 
632 // An internal namespace that is required to implement the C++17 swap traits.
633 // It is not further nested in type_traits_internal to avoid long symbol names.
634 namespace swap_internal {
635 
636 // Necessary for the traits.
637 using std::swap;
638 
639 // This declaration prevents global `swap` and `absl::swap` overloads from being
640 // considered unless ADL picks them up.
641 void swap();
642 
643 template <class T>
644 using IsSwappableImpl = decltype(swap(std::declval<T&>(), std::declval<T&>()));
645 
646 // NOTE: This dance with the default template parameter is for MSVC.
647 template <class T,
648  class IsNoexcept = std::integral_constant<
649  bool, noexcept(swap(std::declval<T&>(), std::declval<T&>()))>>
650 using IsNothrowSwappableImpl = typename std::enable_if<IsNoexcept::value>::type;
651 
652 // IsSwappable
653 //
654 // Determines whether the standard swap idiom is a valid expression for
655 // arguments of type `T`.
656 template <class T>
658  : absl::type_traits_internal::is_detected<IsSwappableImpl, T> {};
659 
660 // IsNothrowSwappable
661 //
662 // Determines whether the standard swap idiom is a valid expression for
663 // arguments of type `T` and is noexcept.
664 template <class T>
666  : absl::type_traits_internal::is_detected<IsNothrowSwappableImpl, T> {};
667 
668 // Swap()
669 //
670 // Performs the swap idiom from a namespace where valid candidates may only be
671 // found in `std` or via ADL.
673 void Swap(T& lhs, T& rhs) noexcept(IsNothrowSwappable<T>::value) {
674  swap(lhs, rhs);
675 }
676 
677 // StdSwapIsUnconstrained
678 //
679 // Some standard library implementations are broken in that they do not
680 // constrain `std::swap`. This will effectively tell us if we are dealing with
681 // one of those implementations.
683 
684 } // namespace swap_internal
685 
686 namespace type_traits_internal {
687 
688 // Make the swap-related traits/function accessible from this namespace.
691 using swap_internal::Swap;
693 
694 } // namespace type_traits_internal
695 } // namespace absl
696 
697 #endif // ABSL_META_TYPE_TRAITS_H_
typename std::result_of< T >::type result_of_t
Definition: type_traits.h:559
typename std::remove_volatile< T >::type remove_volatile_t
Definition: type_traits.h:501
typename std::aligned_storage< Len, Align >::type aligned_storage_t
Definition: type_traits.h:541
typename std::remove_reference< T >::type remove_reference_t
Definition: type_traits.h:513
decltype(swap(std::declval< T & >(), std::declval< T & >())) IsSwappableImpl
Definition: type_traits.h:644
typename std::add_pointer< T >::type add_pointer_t
Definition: type_traits.h:525
typename std::remove_extent< T >::type remove_extent_t
Definition: type_traits.h:534
typename std::enable_if< IsNoexcept::value >::type IsNothrowSwappableImpl
Definition: type_traits.h:650
typename std::decay< T >::type decay_t
Definition: type_traits.h:544
typename std::remove_cv< T >::type remove_cv_t
Definition: type_traits.h:495
typename std::add_lvalue_reference< T >::type add_lvalue_reference_t
Definition: type_traits.h:516
typename std::remove_all_extents< T >::type remove_all_extents_t
Definition: type_traits.h:537
decltype(std::declval< T & >()=std::declval< T && >()) IsMoveAssignableImpl
Definition: type_traits.h:144
Definition: algorithm.h:29
constexpr size_t Align(size_t n, size_t m)
Definition: layout.h:280
typename std::conditional< B, T, F >::type conditional_t
Definition: type_traits.h:550
typename std::remove_const< T >::type remove_const_t
Definition: type_traits.h:498
typename std::enable_if< B, T >::type enable_if_t
Definition: type_traits.h:547
typename std::make_unsigned< T >::type make_unsigned_t
Definition: type_traits.h:531
typename std::make_signed< T >::type make_signed_t
Definition: type_traits.h:528
typename std::add_cv< T >::type add_cv_t
Definition: type_traits.h:504
typename std::add_const< T >::type add_const_t
Definition: type_traits.h:507
void Swap(T &lhs, T &rhs) noexcept(IsNothrowSwappable< T >::value)
Definition: type_traits.h:673
size_t value
typename std::remove_pointer< T >::type remove_pointer_t
Definition: type_traits.h:522
typename std::add_rvalue_reference< T >::type add_rvalue_reference_t
Definition: type_traits.h:519
IsSwappable< void()> StdSwapIsUnconstrained
Definition: type_traits.h:682
void swap(absl::InlinedVector< T, N, A > &a, absl::InlinedVector< T, N, A > &b) noexcept(noexcept(a.swap(b)))
typename std::common_type< T... >::type common_type_t
Definition: type_traits.h:553
typename type_traits_internal::VoidTImpl< Ts... >::type void_t
Definition: type_traits.h:171
decltype(std::declval< T & >()=std::declval< const T & >()) IsCopyAssignableImpl
Definition: type_traits.h:141
typename std::add_volatile< T >::type add_volatile_t
Definition: type_traits.h:510
typename std::underlying_type< T >::type underlying_type_t
Definition: type_traits.h:556
typename std::remove_all_extents< T >::type ExtentsRemoved
Definition: type_traits.h:465


abseil_cpp
Author(s):
autogenerated on Wed Jun 19 2019 19:19:58