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 <cstddef>
39#include <functional>
40#include <type_traits>
41
42#include "absl/base/config.h"
43
44// MSVC constructibility traits do not detect destructor properties and so our
45// implementations should not use them as a source-of-truth.
46#if defined(_MSC_VER) && !defined(__clang__) && !defined(__GNUC__)
47#define ABSL_META_INTERNAL_STD_CONSTRUCTION_TRAITS_DONT_CHECK_DESTRUCTION 1
48#endif
49
50// Defines the default alignment. `__STDCPP_DEFAULT_NEW_ALIGNMENT__` is a C++17
51// feature.
52#if defined(__STDCPP_DEFAULT_NEW_ALIGNMENT__)
53#define ABSL_INTERNAL_DEFAULT_NEW_ALIGNMENT __STDCPP_DEFAULT_NEW_ALIGNMENT__
54#else // defined(__STDCPP_DEFAULT_NEW_ALIGNMENT__)
55#define ABSL_INTERNAL_DEFAULT_NEW_ALIGNMENT alignof(std::max_align_t)
56#endif // defined(__STDCPP_DEFAULT_NEW_ALIGNMENT__)
57
58namespace absl {
59ABSL_NAMESPACE_BEGIN
60
61// Defined and documented later on in this file.
62template <typename T>
63struct is_trivially_destructible;
64
65// Defined and documented later on in this file.
66template <typename T>
67struct is_trivially_move_assignable;
68
69namespace type_traits_internal {
70
71// Silence MSVC warnings about the destructor being defined as deleted.
72#if defined(_MSC_VER) && !defined(__GNUC__)
73#pragma warning(push)
74#pragma warning(disable : 4624)
75#endif // defined(_MSC_VER) && !defined(__GNUC__)
76
77template <class T>
78union SingleMemberUnion {
79 T t;
80};
81
82// Restore the state of the destructor warning that was silenced above.
83#if defined(_MSC_VER) && !defined(__GNUC__)
84#pragma warning(pop)
85#endif // defined(_MSC_VER) && !defined(__GNUC__)
86
87template <class T>
88struct IsTriviallyMoveConstructibleObject
89 : std::integral_constant<
90 bool, std::is_move_constructible<
91 type_traits_internal::SingleMemberUnion<T>>::value &&
92 absl::is_trivially_destructible<T>::value> {};
93
94template <class T>
95struct IsTriviallyCopyConstructibleObject
96 : std::integral_constant<
97 bool, std::is_copy_constructible<
98 type_traits_internal::SingleMemberUnion<T>>::value &&
99 absl::is_trivially_destructible<T>::value> {};
100
101template <class T>
102struct IsTriviallyMoveAssignableReference : std::false_type {};
103
104template <class T>
105struct IsTriviallyMoveAssignableReference<T&>
106 : absl::is_trivially_move_assignable<T>::type {};
107
108template <class T>
109struct IsTriviallyMoveAssignableReference<T&&>
110 : absl::is_trivially_move_assignable<T>::type {};
111
112template <typename... Ts>
113struct VoidTImpl {
114 using type = void;
115};
116
117// This trick to retrieve a default alignment is necessary for our
118// implementation of aligned_storage_t to be consistent with any implementation
119// of std::aligned_storage.
120template <size_t Len, typename T = std::aligned_storage<Len>>
121struct default_alignment_of_aligned_storage;
122
123template <size_t Len, size_t Align>
124struct default_alignment_of_aligned_storage<Len,
125 std::aligned_storage<Len, Align>> {
126 static constexpr size_t value = Align;
127};
128
129////////////////////////////////
130// Library Fundamentals V2 TS //
131////////////////////////////////
132
133// NOTE: The `is_detected` family of templates here differ from the library
134// fundamentals specification in that for library fundamentals, `Op<Args...>` is
135// evaluated as soon as the type `is_detected<Op, Args...>` undergoes
136// substitution, regardless of whether or not the `::value` is accessed. That
137// is inconsistent with all other standard traits and prevents lazy evaluation
138// in larger contexts (such as if the `is_detected` check is a trailing argument
139// of a `conjunction`. This implementation opts to instead be lazy in the same
140// way that the standard traits are (this "defect" of the detection idiom
141// specifications has been reported).
142
143template <class Enabler, template <class...> class Op, class... Args>
144struct is_detected_impl {
145 using type = std::false_type;
146};
147
148template <template <class...> class Op, class... Args>
149struct is_detected_impl<typename VoidTImpl<Op<Args...>>::type, Op, Args...> {
150 using type = std::true_type;
151};
152
153template <template <class...> class Op, class... Args>
154struct is_detected : is_detected_impl<void, Op, Args...>::type {};
155
156template <class Enabler, class To, template <class...> class Op, class... Args>
157struct is_detected_convertible_impl {
158 using type = std::false_type;
159};
160
161template <class To, template <class...> class Op, class... Args>
162struct is_detected_convertible_impl<
163 typename std::enable_if<std::is_convertible<Op<Args...>, To>::value>::type,
164 To, Op, Args...> {
165 using type = std::true_type;
166};
167
168template <class To, template <class...> class Op, class... Args>
169struct is_detected_convertible
170 : is_detected_convertible_impl<void, To, Op, Args...>::type {};
171
172template <typename T>
173using IsCopyAssignableImpl =
174 decltype(std::declval<T&>() = std::declval<const T&>());
175
176template <typename T>
177using IsMoveAssignableImpl = decltype(std::declval<T&>() = std::declval<T&&>());
178
179} // namespace type_traits_internal
180
181// MSVC 19.20 has a regression that causes our workarounds to fail, but their
182// std forms now appear to be compliant.
183#if defined(_MSC_VER) && !defined(__clang__) && (_MSC_VER >= 1920)
184
185template <typename T>
186using is_copy_assignable = std::is_copy_assignable<T>;
187
188template <typename T>
189using is_move_assignable = std::is_move_assignable<T>;
190
191#else
192
193template <typename T>
194struct is_copy_assignable : type_traits_internal::is_detected<
195 type_traits_internal::IsCopyAssignableImpl, T> {
196};
197
198template <typename T>
199struct is_move_assignable : type_traits_internal::is_detected<
200 type_traits_internal::IsMoveAssignableImpl, T> {
201};
202
203#endif
204
205// void_t()
206//
207// Ignores the type of any its arguments and returns `void`. In general, this
208// metafunction allows you to create a general case that maps to `void` while
209// allowing specializations that map to specific types.
210//
211// This metafunction is designed to be a drop-in replacement for the C++17
212// `std::void_t` metafunction.
213//
214// NOTE: `absl::void_t` does not use the standard-specified implementation so
215// that it can remain compatible with gcc < 5.1. This can introduce slightly
216// different behavior, such as when ordering partial specializations.
217template <typename... Ts>
218using void_t = typename type_traits_internal::VoidTImpl<Ts...>::type;
219
220// conjunction
221//
222// Performs a compile-time logical AND operation on the passed types (which
223// must have `::value` members convertible to `bool`. Short-circuits if it
224// encounters any `false` members (and does not compare the `::value` members
225// of any remaining arguments).
226//
227// This metafunction is designed to be a drop-in replacement for the C++17
228// `std::conjunction` metafunction.
229template <typename... Ts>
230struct conjunction : std::true_type {};
231
232template <typename T, typename... Ts>
233struct conjunction<T, Ts...>
234 : std::conditional<T::value, conjunction<Ts...>, T>::type {};
235
236template <typename T>
237struct conjunction<T> : T {};
238
239// disjunction
240//
241// Performs a compile-time logical OR operation on the passed types (which
242// must have `::value` members convertible to `bool`. Short-circuits if it
243// encounters any `true` members (and does not compare the `::value` members
244// of any remaining arguments).
245//
246// This metafunction is designed to be a drop-in replacement for the C++17
247// `std::disjunction` metafunction.
248template <typename... Ts>
249struct disjunction : std::false_type {};
250
251template <typename T, typename... Ts>
252struct disjunction<T, Ts...> :
253 std::conditional<T::value, T, disjunction<Ts...>>::type {};
254
255template <typename T>
256struct disjunction<T> : T {};
257
258// negation
259//
260// Performs a compile-time logical NOT operation on the passed type (which
261// must have `::value` members convertible to `bool`.
262//
263// This metafunction is designed to be a drop-in replacement for the C++17
264// `std::negation` metafunction.
265template <typename T>
266struct negation : std::integral_constant<bool, !T::value> {};
267
268// is_function()
269//
270// Determines whether the passed type `T` is a function type.
271//
272// This metafunction is designed to be a drop-in replacement for the C++11
273// `std::is_function()` metafunction for platforms that have incomplete C++11
274// support (such as libstdc++ 4.x).
275//
276// This metafunction works because appending `const` to a type does nothing to
277// function types and reference types (and forms a const-qualified type
278// otherwise).
279template <typename T>
280struct is_function
281 : std::integral_constant<
282 bool, !(std::is_reference<T>::value ||
283 std::is_const<typename std::add_const<T>::type>::value)> {};
284
285// is_trivially_destructible()
286//
287// Determines whether the passed type `T` is trivially destructible.
288//
289// This metafunction is designed to be a drop-in replacement for the C++11
290// `std::is_trivially_destructible()` metafunction for platforms that have
291// incomplete C++11 support (such as libstdc++ 4.x). On any platforms that do
292// fully support C++11, we check whether this yields the same result as the std
293// implementation.
294//
295// NOTE: the extensions (__has_trivial_xxx) are implemented in gcc (version >=
296// 4.3) and clang. Since we are supporting libstdc++ > 4.7, they should always
297// be present. These extensions are documented at
298// https://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html#Type-Traits.
299template <typename T>
300struct is_trivially_destructible
301 : std::integral_constant<bool, __has_trivial_destructor(T) &&
302 std::is_destructible<T>::value> {
303#ifdef ABSL_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE
304 private:
305 static constexpr bool compliant = std::is_trivially_destructible<T>::value ==
306 is_trivially_destructible::value;
307 static_assert(compliant || std::is_trivially_destructible<T>::value,
308 "Not compliant with std::is_trivially_destructible; "
309 "Standard: false, Implementation: true");
310 static_assert(compliant || !std::is_trivially_destructible<T>::value,
311 "Not compliant with std::is_trivially_destructible; "
312 "Standard: true, Implementation: false");
313#endif // ABSL_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE
314};
315
316// is_trivially_default_constructible()
317//
318// Determines whether the passed type `T` is trivially default constructible.
319//
320// This metafunction is designed to be a drop-in replacement for the C++11
321// `std::is_trivially_default_constructible()` metafunction for platforms that
322// have incomplete C++11 support (such as libstdc++ 4.x). On any platforms that
323// do fully support C++11, we check whether this yields the same result as the
324// std implementation.
325//
326// NOTE: according to the C++ standard, Section: 20.15.4.3 [meta.unary.prop]
327// "The predicate condition for a template specialization is_constructible<T,
328// Args...> shall be satisfied if and only if the following variable
329// definition would be well-formed for some invented variable t:
330//
331// T t(declval<Args>()...);
332//
333// is_trivially_constructible<T, Args...> additionally requires that the
334// variable definition does not call any operation that is not trivial.
335// For the purposes of this check, the call to std::declval is considered
336// trivial."
337//
338// Notes from https://en.cppreference.com/w/cpp/types/is_constructible:
339// In many implementations, is_nothrow_constructible also checks if the
340// destructor throws because it is effectively noexcept(T(arg)). Same
341// applies to is_trivially_constructible, which, in these implementations, also
342// requires that the destructor is trivial.
343// GCC bug 51452: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51452
344// LWG issue 2116: http://cplusplus.github.io/LWG/lwg-active.html#2116.
345//
346// "T obj();" need to be well-formed and not call any nontrivial operation.
347// Nontrivially destructible types will cause the expression to be nontrivial.
348template <typename T>
349struct is_trivially_default_constructible
350 : std::integral_constant<bool, __has_trivial_constructor(T) &&
351 std::is_default_constructible<T>::value &&
352 is_trivially_destructible<T>::value> {
353#if defined(ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE) && \
354 !defined( \
355 ABSL_META_INTERNAL_STD_CONSTRUCTION_TRAITS_DONT_CHECK_DESTRUCTION)
356 private:
357 static constexpr bool compliant =
358 std::is_trivially_default_constructible<T>::value ==
359 is_trivially_default_constructible::value;
360 static_assert(compliant || std::is_trivially_default_constructible<T>::value,
361 "Not compliant with std::is_trivially_default_constructible; "
362 "Standard: false, Implementation: true");
363 static_assert(compliant || !std::is_trivially_default_constructible<T>::value,
364 "Not compliant with std::is_trivially_default_constructible; "
365 "Standard: true, Implementation: false");
366#endif // ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE
367};
368
369// is_trivially_move_constructible()
370//
371// Determines whether the passed type `T` is trivially move constructible.
372//
373// This metafunction is designed to be a drop-in replacement for the C++11
374// `std::is_trivially_move_constructible()` metafunction for platforms that have
375// incomplete C++11 support (such as libstdc++ 4.x). On any platforms that do
376// fully support C++11, we check whether this yields the same result as the std
377// implementation.
378//
379// NOTE: `T obj(declval<T>());` needs to be well-formed and not call any
380// nontrivial operation. Nontrivially destructible types will cause the
381// expression to be nontrivial.
382template <typename T>
383struct is_trivially_move_constructible
384 : std::conditional<
385 std::is_object<T>::value && !std::is_array<T>::value,
386 type_traits_internal::IsTriviallyMoveConstructibleObject<T>,
387 std::is_reference<T>>::type::type {
388#if defined(ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE) && \
389 !defined( \
390 ABSL_META_INTERNAL_STD_CONSTRUCTION_TRAITS_DONT_CHECK_DESTRUCTION)
391 private:
392 static constexpr bool compliant =
393 std::is_trivially_move_constructible<T>::value ==
394 is_trivially_move_constructible::value;
395 static_assert(compliant || std::is_trivially_move_constructible<T>::value,
396 "Not compliant with std::is_trivially_move_constructible; "
397 "Standard: false, Implementation: true");
398 static_assert(compliant || !std::is_trivially_move_constructible<T>::value,
399 "Not compliant with std::is_trivially_move_constructible; "
400 "Standard: true, Implementation: false");
401#endif // ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE
402};
403
404// is_trivially_copy_constructible()
405//
406// Determines whether the passed type `T` is trivially copy constructible.
407//
408// This metafunction is designed to be a drop-in replacement for the C++11
409// `std::is_trivially_copy_constructible()` metafunction for platforms that have
410// incomplete C++11 support (such as libstdc++ 4.x). On any platforms that do
411// fully support C++11, we check whether this yields the same result as the std
412// implementation.
413//
414// NOTE: `T obj(declval<const T&>());` needs to be well-formed and not call any
415// nontrivial operation. Nontrivially destructible types will cause the
416// expression to be nontrivial.
417template <typename T>
418struct is_trivially_copy_constructible
419 : std::conditional<
420 std::is_object<T>::value && !std::is_array<T>::value,
421 type_traits_internal::IsTriviallyCopyConstructibleObject<T>,
422 std::is_lvalue_reference<T>>::type::type {
423#if defined(ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE) && \
424 !defined( \
425 ABSL_META_INTERNAL_STD_CONSTRUCTION_TRAITS_DONT_CHECK_DESTRUCTION)
426 private:
427 static constexpr bool compliant =
428 std::is_trivially_copy_constructible<T>::value ==
429 is_trivially_copy_constructible::value;
430 static_assert(compliant || std::is_trivially_copy_constructible<T>::value,
431 "Not compliant with std::is_trivially_copy_constructible; "
432 "Standard: false, Implementation: true");
433 static_assert(compliant || !std::is_trivially_copy_constructible<T>::value,
434 "Not compliant with std::is_trivially_copy_constructible; "
435 "Standard: true, Implementation: false");
436#endif // ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE
437};
438
439// is_trivially_move_assignable()
440//
441// Determines whether the passed type `T` is trivially move assignable.
442//
443// This metafunction is designed to be a drop-in replacement for the C++11
444// `std::is_trivially_move_assignable()` metafunction for platforms that have
445// incomplete C++11 support (such as libstdc++ 4.x). On any platforms that do
446// fully support C++11, we check whether this yields the same result as the std
447// implementation.
448//
449// NOTE: `is_assignable<T, U>::value` is `true` if the expression
450// `declval<T>() = declval<U>()` is well-formed when treated as an unevaluated
451// operand. `is_trivially_assignable<T, U>` requires the assignment to call no
452// operation that is not trivial. `is_trivially_copy_assignable<T>` is simply
453// `is_trivially_assignable<T&, T>`.
454template <typename T>
455struct is_trivially_move_assignable
456 : std::conditional<
457 std::is_object<T>::value && !std::is_array<T>::value &&
458 std::is_move_assignable<T>::value,
459 std::is_move_assignable<type_traits_internal::SingleMemberUnion<T>>,
460 type_traits_internal::IsTriviallyMoveAssignableReference<T>>::type::
461 type {
462#ifdef ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE
463 private:
464 static constexpr bool compliant =
465 std::is_trivially_move_assignable<T>::value ==
466 is_trivially_move_assignable::value;
467 static_assert(compliant || std::is_trivially_move_assignable<T>::value,
468 "Not compliant with std::is_trivially_move_assignable; "
469 "Standard: false, Implementation: true");
470 static_assert(compliant || !std::is_trivially_move_assignable<T>::value,
471 "Not compliant with std::is_trivially_move_assignable; "
472 "Standard: true, Implementation: false");
473#endif // ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE
474};
475
476// is_trivially_copy_assignable()
477//
478// Determines whether the passed type `T` is trivially copy assignable.
479//
480// This metafunction is designed to be a drop-in replacement for the C++11
481// `std::is_trivially_copy_assignable()` metafunction for platforms that have
482// incomplete C++11 support (such as libstdc++ 4.x). On any platforms that do
483// fully support C++11, we check whether this yields the same result as the std
484// implementation.
485//
486// NOTE: `is_assignable<T, U>::value` is `true` if the expression
487// `declval<T>() = declval<U>()` is well-formed when treated as an unevaluated
488// operand. `is_trivially_assignable<T, U>` requires the assignment to call no
489// operation that is not trivial. `is_trivially_copy_assignable<T>` is simply
490// `is_trivially_assignable<T&, const T&>`.
491template <typename T>
492struct is_trivially_copy_assignable
493 : std::integral_constant<
494 bool, __has_trivial_assign(typename std::remove_reference<T>::type) &&
495 absl::is_copy_assignable<T>::value> {
496#ifdef ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE
497 private:
498 static constexpr bool compliant =
499 std::is_trivially_copy_assignable<T>::value ==
500 is_trivially_copy_assignable::value;
501 static_assert(compliant || std::is_trivially_copy_assignable<T>::value,
502 "Not compliant with std::is_trivially_copy_assignable; "
503 "Standard: false, Implementation: true");
504 static_assert(compliant || !std::is_trivially_copy_assignable<T>::value,
505 "Not compliant with std::is_trivially_copy_assignable; "
506 "Standard: true, Implementation: false");
507#endif // ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE
508};
509
510#if defined(__cpp_lib_remove_cvref) && __cpp_lib_remove_cvref >= 201711L
511template <typename T>
512using remove_cvref = std::remove_cvref<T>;
513
514template <typename T>
515using remove_cvref_t = typename std::remove_cvref<T>::type;
516#else
517// remove_cvref()
518//
519// C++11 compatible implementation of std::remove_cvref which was added in
520// C++20.
521template <typename T>
522struct remove_cvref {
523 using type =
524 typename std::remove_cv<typename std::remove_reference<T>::type>::type;
525};
526
527template <typename T>
528using remove_cvref_t = typename remove_cvref<T>::type;
529#endif
530
531namespace type_traits_internal {
532// is_trivially_copyable()
533//
534// Determines whether the passed type `T` is trivially copyable.
535//
536// This metafunction is designed to be a drop-in replacement for the C++11
537// `std::is_trivially_copyable()` metafunction for platforms that have
538// incomplete C++11 support (such as libstdc++ 4.x). We use the C++17 definition
539// of TriviallyCopyable.
540//
541// NOTE: `is_trivially_copyable<T>::value` is `true` if all of T's copy/move
542// constructors/assignment operators are trivial or deleted, T has at least
543// one non-deleted copy/move constructor/assignment operator, and T is trivially
544// destructible. Arrays of trivially copyable types are trivially copyable.
545//
546// We expose this metafunction only for internal use within absl.
547template <typename T>
548class is_trivially_copyable_impl {
549 using ExtentsRemoved = typename std::remove_all_extents<T>::type;
550 static constexpr bool kIsCopyOrMoveConstructible =
551 std::is_copy_constructible<ExtentsRemoved>::value ||
552 std::is_move_constructible<ExtentsRemoved>::value;
553 static constexpr bool kIsCopyOrMoveAssignable =
554 absl::is_copy_assignable<ExtentsRemoved>::value ||
555 absl::is_move_assignable<ExtentsRemoved>::value;
556
557 public:
558 static constexpr bool kValue =
559 (__has_trivial_copy(ExtentsRemoved) || !kIsCopyOrMoveConstructible) &&
560 (__has_trivial_assign(ExtentsRemoved) || !kIsCopyOrMoveAssignable) &&
561 (kIsCopyOrMoveConstructible || kIsCopyOrMoveAssignable) &&
562 is_trivially_destructible<ExtentsRemoved>::value &&
563 // We need to check for this explicitly because otherwise we'll say
564 // references are trivial copyable when compiled by MSVC.
565 !std::is_reference<ExtentsRemoved>::value;
566};
567
568template <typename T>
569struct is_trivially_copyable
570 : std::integral_constant<
571 bool, type_traits_internal::is_trivially_copyable_impl<T>::kValue> {};
572} // namespace type_traits_internal
573
574// -----------------------------------------------------------------------------
575// C++14 "_t" trait aliases
576// -----------------------------------------------------------------------------
577
578template <typename T>
579using remove_cv_t = typename std::remove_cv<T>::type;
580
581template <typename T>
582using remove_const_t = typename std::remove_const<T>::type;
583
584template <typename T>
585using remove_volatile_t = typename std::remove_volatile<T>::type;
586
587template <typename T>
588using add_cv_t = typename std::add_cv<T>::type;
589
590template <typename T>
591using add_const_t = typename std::add_const<T>::type;
592
593template <typename T>
594using add_volatile_t = typename std::add_volatile<T>::type;
595
596template <typename T>
597using remove_reference_t = typename std::remove_reference<T>::type;
598
599template <typename T>
600using add_lvalue_reference_t = typename std::add_lvalue_reference<T>::type;
601
602template <typename T>
603using add_rvalue_reference_t = typename std::add_rvalue_reference<T>::type;
604
605template <typename T>
606using remove_pointer_t = typename std::remove_pointer<T>::type;
607
608template <typename T>
609using add_pointer_t = typename std::add_pointer<T>::type;
610
611template <typename T>
612using make_signed_t = typename std::make_signed<T>::type;
613
614template <typename T>
615using make_unsigned_t = typename std::make_unsigned<T>::type;
616
617template <typename T>
618using remove_extent_t = typename std::remove_extent<T>::type;
619
620template <typename T>
621using remove_all_extents_t = typename std::remove_all_extents<T>::type;
622
623template <size_t Len, size_t Align = type_traits_internal::
624 default_alignment_of_aligned_storage<Len>::value>
625using aligned_storage_t = typename std::aligned_storage<Len, Align>::type;
626
627template <typename T>
628using decay_t = typename std::decay<T>::type;
629
630template <bool B, typename T = void>
631using enable_if_t = typename std::enable_if<B, T>::type;
632
633template <bool B, typename T, typename F>
634using conditional_t = typename std::conditional<B, T, F>::type;
635
636template <typename... T>
637using common_type_t = typename std::common_type<T...>::type;
638
639template <typename T>
640using underlying_type_t = typename std::underlying_type<T>::type;
641
642
643namespace type_traits_internal {
644
645#if (defined(__cpp_lib_is_invocable) && __cpp_lib_is_invocable >= 201703L) || \
646 (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
647// std::result_of is deprecated (C++17) or removed (C++20)
648template<typename> struct result_of;
649template<typename F, typename... Args>
650struct result_of<F(Args...)> : std::invoke_result<F, Args...> {};
651#else
652template<typename F> using result_of = std::result_of<F>;
653#endif
654
655} // namespace type_traits_internal
656
657template<typename F>
658using result_of_t = typename type_traits_internal::result_of<F>::type;
659
660namespace type_traits_internal {
661// In MSVC we can't probe std::hash or stdext::hash because it triggers a
662// static_assert instead of failing substitution. Libc++ prior to 4.0
663// also used a static_assert.
664//
665#if defined(_MSC_VER) || (defined(_LIBCPP_VERSION) && \
666 _LIBCPP_VERSION < 4000 && _LIBCPP_STD_VER > 11)
667#define ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_ 0
668#else
669#define ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_ 1
670#endif
671
672#if !ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
673template <typename Key, typename = size_t>
674struct IsHashable : std::true_type {};
675#else // ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
676template <typename Key, typename = void>
677struct IsHashable : std::false_type {};
678
679template <typename Key>
680struct IsHashable<
681 Key,
682 absl::enable_if_t<std::is_convertible<
683 decltype(std::declval<std::hash<Key>&>()(std::declval<Key const&>())),
684 std::size_t>::value>> : std::true_type {};
685#endif // !ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
686
687struct AssertHashEnabledHelper {
688 private:
689 static void Sink(...) {}
690 struct NAT {};
691
692 template <class Key>
693 static auto GetReturnType(int)
694 -> decltype(std::declval<std::hash<Key>>()(std::declval<Key const&>()));
695 template <class Key>
696 static NAT GetReturnType(...);
697
698 template <class Key>
699 static std::nullptr_t DoIt() {
700 static_assert(IsHashable<Key>::value,
701 "std::hash<Key> does not provide a call operator");
702 static_assert(
703 std::is_default_constructible<std::hash<Key>>::value,
704 "std::hash<Key> must be default constructible when it is enabled");
705 static_assert(
706 std::is_copy_constructible<std::hash<Key>>::value,
707 "std::hash<Key> must be copy constructible when it is enabled");
708 static_assert(absl::is_copy_assignable<std::hash<Key>>::value,
709 "std::hash<Key> must be copy assignable when it is enabled");
710 // is_destructible is unchecked as it's implied by each of the
711 // is_constructible checks.
712 using ReturnType = decltype(GetReturnType<Key>(0));
713 static_assert(std::is_same<ReturnType, NAT>::value ||
714 std::is_same<ReturnType, size_t>::value,
715 "std::hash<Key> must return size_t");
716 return nullptr;
717 }
718
719 template <class... Ts>
720 friend void AssertHashEnabled();
721};
722
723template <class... Ts>
724inline void AssertHashEnabled() {
725 using Helper = AssertHashEnabledHelper;
726 Helper::Sink(Helper::DoIt<Ts>()...);
727}
728
729} // namespace type_traits_internal
730
731// An internal namespace that is required to implement the C++17 swap traits.
732// It is not further nested in type_traits_internal to avoid long symbol names.
733namespace swap_internal {
734
735// Necessary for the traits.
736using std::swap;
737
738// This declaration prevents global `swap` and `absl::swap` overloads from being
739// considered unless ADL picks them up.
740void swap();
741
742template <class T>
743using IsSwappableImpl = decltype(swap(std::declval<T&>(), std::declval<T&>()));
744
745// NOTE: This dance with the default template parameter is for MSVC.
746template <class T,
747 class IsNoexcept = std::integral_constant<
748 bool, noexcept(swap(std::declval<T&>(), std::declval<T&>()))>>
749using IsNothrowSwappableImpl = typename std::enable_if<IsNoexcept::value>::type;
750
751// IsSwappable
752//
753// Determines whether the standard swap idiom is a valid expression for
754// arguments of type `T`.
755template <class T>
756struct IsSwappable
757 : absl::type_traits_internal::is_detected<IsSwappableImpl, T> {};
758
759// IsNothrowSwappable
760//
761// Determines whether the standard swap idiom is a valid expression for
762// arguments of type `T` and is noexcept.
763template <class T>
764struct IsNothrowSwappable
765 : absl::type_traits_internal::is_detected<IsNothrowSwappableImpl, T> {};
766
767// Swap()
768//
769// Performs the swap idiom from a namespace where valid candidates may only be
770// found in `std` or via ADL.
771template <class T, absl::enable_if_t<IsSwappable<T>::value, int> = 0>
772void Swap(T& lhs, T& rhs) noexcept(IsNothrowSwappable<T>::value) {
773 swap(lhs, rhs);
774}
775
776// StdSwapIsUnconstrained
777//
778// Some standard library implementations are broken in that they do not
779// constrain `std::swap`. This will effectively tell us if we are dealing with
780// one of those implementations.
781using StdSwapIsUnconstrained = IsSwappable<void()>;
782
783} // namespace swap_internal
784
785namespace type_traits_internal {
786
787// Make the swap-related traits/function accessible from this namespace.
788using swap_internal::IsNothrowSwappable;
789using swap_internal::IsSwappable;
790using swap_internal::Swap;
791using swap_internal::StdSwapIsUnconstrained;
792
793} // namespace type_traits_internal
794ABSL_NAMESPACE_END
795} // namespace absl
796
797#endif // ABSL_META_TYPE_TRAITS_H_
798

source code of include/absl/meta/type_traits.h