2 // Copyright 2017 The Abseil Authors.
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
8 // https://www.apache.org/licenses/LICENSE-2.0
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.
16 // -----------------------------------------------------------------------------
18 // -----------------------------------------------------------------------------
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.
25 // See https://en.cppreference.com/w/cpp/header/type_traits
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
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 OTABSL_META_TYPE_TRAITS_H_
36 #define OTABSL_META_TYPE_TRAITS_H_
40 #include <type_traits>
42 #include "../base/config.h"
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 OTABSL_META_INTERNAL_STD_CONSTRUCTION_TRAITS_DONT_CHECK_DESTRUCTION 1
51 OTABSL_NAMESPACE_BEGIN
53 // Defined and documented later on in this file.
55 struct is_trivially_destructible
;
57 // Defined and documented later on in this file.
59 struct is_trivially_move_assignable
;
61 namespace type_traits_internal
{
63 // Silence MSVC warnings about the destructor being defined as deleted.
64 #if defined(_MSC_VER) && !defined(__GNUC__)
66 #pragma warning(disable : 4624)
67 #endif // defined(_MSC_VER) && !defined(__GNUC__)
70 union SingleMemberUnion
{
74 // Restore the state of the destructor warning that was silenced above.
75 #if defined(_MSC_VER) && !defined(__GNUC__)
77 #endif // defined(_MSC_VER) && !defined(__GNUC__)
80 struct IsTriviallyMoveConstructibleObject
81 : std::integral_constant
<
82 bool, std::is_move_constructible
<
83 type_traits_internal::SingleMemberUnion
<T
>>::value
&&
84 absl::is_trivially_destructible
<T
>::value
> {};
87 struct IsTriviallyCopyConstructibleObject
88 : std::integral_constant
<
89 bool, std::is_copy_constructible
<
90 type_traits_internal::SingleMemberUnion
<T
>>::value
&&
91 absl::is_trivially_destructible
<T
>::value
> {};
94 struct IsTriviallyMoveAssignableReference
: std::false_type
{};
97 struct IsTriviallyMoveAssignableReference
<T
&>
98 : absl::is_trivially_move_assignable
<T
>::type
{};
101 struct IsTriviallyMoveAssignableReference
<T
&&>
102 : absl::is_trivially_move_assignable
<T
>::type
{};
104 template <typename
... Ts
>
109 // This trick to retrieve a default alignment is necessary for our
110 // implementation of aligned_storage_t to be consistent with any implementation
111 // of std::aligned_storage.
112 template <size_t Len
, typename T
= std::aligned_storage
<Len
>>
113 struct default_alignment_of_aligned_storage
;
115 template <size_t Len
, size_t Align
>
116 struct default_alignment_of_aligned_storage
<Len
,
117 std::aligned_storage
<Len
, Align
>> {
118 static constexpr size_t value
= Align
;
121 ////////////////////////////////
122 // Library Fundamentals V2 TS //
123 ////////////////////////////////
125 // NOTE: The `is_detected` family of templates here differ from the library
126 // fundamentals specification in that for library fundamentals, `Op<Args...>` is
127 // evaluated as soon as the type `is_detected<Op, Args...>` undergoes
128 // substitution, regardless of whether or not the `::value` is accessed. That
129 // is inconsistent with all other standard traits and prevents lazy evaluation
130 // in larger contexts (such as if the `is_detected` check is a trailing argument
131 // of a `conjunction`. This implementation opts to instead be lazy in the same
132 // way that the standard traits are (this "defect" of the detection idiom
133 // specifications has been reported).
135 template <class Enabler
, template <class...> class Op
, class... Args
>
136 struct is_detected_impl
{
137 using type
= std::false_type
;
140 template <template <class...> class Op
, class... Args
>
141 struct is_detected_impl
<typename VoidTImpl
<Op
<Args
...>>::type
, Op
, Args
...> {
142 using type
= std::true_type
;
145 template <template <class...> class Op
, class... Args
>
146 struct is_detected
: is_detected_impl
<void, Op
, Args
...>::type
{};
148 template <class Enabler
, class To
, template <class...> class Op
, class... Args
>
149 struct is_detected_convertible_impl
{
150 using type
= std::false_type
;
153 template <class To
, template <class...> class Op
, class... Args
>
154 struct is_detected_convertible_impl
<
155 typename
std::enable_if
<std::is_convertible
<Op
<Args
...>, To
>::value
>::type
,
157 using type
= std::true_type
;
160 template <class To
, template <class...> class Op
, class... Args
>
161 struct is_detected_convertible
162 : is_detected_convertible_impl
<void, To
, Op
, Args
...>::type
{};
164 template <typename T
>
165 using IsCopyAssignableImpl
=
166 decltype(std::declval
<T
&>() = std::declval
<const T
&>());
168 template <typename T
>
169 using IsMoveAssignableImpl
= decltype(std::declval
<T
&>() = std::declval
<T
&&>());
171 } // namespace type_traits_internal
173 // MSVC 19.20 has a regression that causes our workarounds to fail, but their
174 // std forms now appear to be compliant.
175 #if defined(_MSC_VER) && !defined(__clang__) && (_MSC_VER >= 1920)
177 template <typename T
>
178 using is_copy_assignable
= std::is_copy_assignable
<T
>;
180 template <typename T
>
181 using is_move_assignable
= std::is_move_assignable
<T
>;
185 template <typename T
>
186 struct is_copy_assignable
: type_traits_internal::is_detected
<
187 type_traits_internal::IsCopyAssignableImpl
, T
> {
190 template <typename T
>
191 struct is_move_assignable
: type_traits_internal::is_detected
<
192 type_traits_internal::IsMoveAssignableImpl
, T
> {
199 // Ignores the type of any its arguments and returns `void`. In general, this
200 // metafunction allows you to create a general case that maps to `void` while
201 // allowing specializations that map to specific types.
203 // This metafunction is designed to be a drop-in replacement for the C++17
204 // `std::void_t` metafunction.
206 // NOTE: `absl::void_t` does not use the standard-specified implementation so
207 // that it can remain compatible with gcc < 5.1. This can introduce slightly
208 // different behavior, such as when ordering partial specializations.
209 template <typename
... Ts
>
210 using void_t
= typename
type_traits_internal::VoidTImpl
<Ts
...>::type
;
214 // Performs a compile-time logical AND operation on the passed types (which
215 // must have `::value` members convertible to `bool`. Short-circuits if it
216 // encounters any `false` members (and does not compare the `::value` members
217 // of any remaining arguments).
219 // This metafunction is designed to be a drop-in replacement for the C++17
220 // `std::conjunction` metafunction.
221 template <typename
... Ts
>
224 template <typename T
, typename
... Ts
>
225 struct conjunction
<T
, Ts
...>
226 : std::conditional
<T::value
, conjunction
<Ts
...>, T
>::type
{};
228 template <typename T
>
229 struct conjunction
<T
> : T
{};
232 struct conjunction
<> : std::true_type
{};
236 // Performs a compile-time logical OR operation on the passed types (which
237 // must have `::value` members convertible to `bool`. Short-circuits if it
238 // encounters any `true` members (and does not compare the `::value` members
239 // of any remaining arguments).
241 // This metafunction is designed to be a drop-in replacement for the C++17
242 // `std::disjunction` metafunction.
243 template <typename
... Ts
>
246 template <typename T
, typename
... Ts
>
247 struct disjunction
<T
, Ts
...> :
248 std::conditional
<T::value
, T
, disjunction
<Ts
...>>::type
{};
250 template <typename T
>
251 struct disjunction
<T
> : T
{};
254 struct disjunction
<> : std::false_type
{};
258 // Performs a compile-time logical NOT operation on the passed type (which
259 // must have `::value` members convertible to `bool`.
261 // This metafunction is designed to be a drop-in replacement for the C++17
262 // `std::negation` metafunction.
263 template <typename T
>
264 struct negation
: std::integral_constant
<bool, !T::value
> {};
268 // Determines whether the passed type `T` is a function type.
270 // This metafunction is designed to be a drop-in replacement for the C++11
271 // `std::is_function()` metafunction for platforms that have incomplete C++11
272 // support (such as libstdc++ 4.x).
274 // This metafunction works because appending `const` to a type does nothing to
275 // function types and reference types (and forms a const-qualified type
277 template <typename T
>
279 : std::integral_constant
<
280 bool, !(std::is_reference
<T
>::value
||
281 std::is_const
<typename
std::add_const
<T
>::type
>::value
)> {};
283 // is_trivially_destructible()
285 // Determines whether the passed type `T` is trivially destructible.
287 // This metafunction is designed to be a drop-in replacement for the C++11
288 // `std::is_trivially_destructible()` metafunction for platforms that have
289 // incomplete C++11 support (such as libstdc++ 4.x). On any platforms that do
290 // fully support C++11, we check whether this yields the same result as the std
293 // NOTE: the extensions (__has_trivial_xxx) are implemented in gcc (version >=
294 // 4.3) and clang. Since we are supporting libstdc++ > 4.7, they should always
295 // be present. These extensions are documented at
296 // https://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html#Type-Traits.
297 template <typename T
>
298 struct is_trivially_destructible
299 : std::integral_constant
<bool, __has_trivial_destructor(T
) &&
300 std::is_destructible
<T
>::value
> {
301 #ifdef OTABSL_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE
303 static constexpr bool compliant
= std::is_trivially_destructible
<T
>::value
==
304 is_trivially_destructible::value
;
305 static_assert(compliant
|| std::is_trivially_destructible
<T
>::value
,
306 "Not compliant with std::is_trivially_destructible; "
307 "Standard: false, Implementation: true");
308 static_assert(compliant
|| !std::is_trivially_destructible
<T
>::value
,
309 "Not compliant with std::is_trivially_destructible; "
310 "Standard: true, Implementation: false");
311 #endif // OTABSL_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE
314 // is_trivially_default_constructible()
316 // Determines whether the passed type `T` is trivially default constructible.
318 // This metafunction is designed to be a drop-in replacement for the C++11
319 // `std::is_trivially_default_constructible()` metafunction for platforms that
320 // have incomplete C++11 support (such as libstdc++ 4.x). On any platforms that
321 // do fully support C++11, we check whether this yields the same result as the
322 // std implementation.
324 // NOTE: according to the C++ standard, Section: 20.15.4.3 [meta.unary.prop]
325 // "The predicate condition for a template specialization is_constructible<T,
326 // Args...> shall be satisfied if and only if the following variable
327 // definition would be well-formed for some invented variable t:
329 // T t(declval<Args>()...);
331 // is_trivially_constructible<T, Args...> additionally requires that the
332 // variable definition does not call any operation that is not trivial.
333 // For the purposes of this check, the call to std::declval is considered
336 // Notes from https://en.cppreference.com/w/cpp/types/is_constructible:
337 // In many implementations, is_nothrow_constructible also checks if the
338 // destructor throws because it is effectively noexcept(T(arg)). Same
339 // applies to is_trivially_constructible, which, in these implementations, also
340 // requires that the destructor is trivial.
341 // GCC bug 51452: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51452
342 // LWG issue 2116: http://cplusplus.github.io/LWG/lwg-active.html#2116.
344 // "T obj();" need to be well-formed and not call any nontrivial operation.
345 // Nontrivially destructible types will cause the expression to be nontrivial.
346 template <typename T
>
347 struct is_trivially_default_constructible
348 : std::integral_constant
<bool, __has_trivial_constructor(T
) &&
349 std::is_default_constructible
<T
>::value
&&
350 is_trivially_destructible
<T
>::value
> {
351 #if defined(OTABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE) && \
353 OTABSL_META_INTERNAL_STD_CONSTRUCTION_TRAITS_DONT_CHECK_DESTRUCTION)
355 static constexpr bool compliant
=
356 std::is_trivially_default_constructible
<T
>::value
==
357 is_trivially_default_constructible::value
;
358 static_assert(compliant
|| std::is_trivially_default_constructible
<T
>::value
,
359 "Not compliant with std::is_trivially_default_constructible; "
360 "Standard: false, Implementation: true");
361 static_assert(compliant
|| !std::is_trivially_default_constructible
<T
>::value
,
362 "Not compliant with std::is_trivially_default_constructible; "
363 "Standard: true, Implementation: false");
364 #endif // OTABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE
367 // is_trivially_move_constructible()
369 // Determines whether the passed type `T` is trivially move constructible.
371 // This metafunction is designed to be a drop-in replacement for the C++11
372 // `std::is_trivially_move_constructible()` metafunction for platforms that have
373 // incomplete C++11 support (such as libstdc++ 4.x). On any platforms that do
374 // fully support C++11, we check whether this yields the same result as the std
377 // NOTE: `T obj(declval<T>());` needs to be well-formed and not call any
378 // nontrivial operation. Nontrivially destructible types will cause the
379 // expression to be nontrivial.
380 template <typename T
>
381 struct is_trivially_move_constructible
383 std::is_object
<T
>::value
&& !std::is_array
<T
>::value
,
384 type_traits_internal::IsTriviallyMoveConstructibleObject
<T
>,
385 std::is_reference
<T
>>::type::type
{
386 #if defined(OTABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE) && \
388 OTABSL_META_INTERNAL_STD_CONSTRUCTION_TRAITS_DONT_CHECK_DESTRUCTION)
390 static constexpr bool compliant
=
391 std::is_trivially_move_constructible
<T
>::value
==
392 is_trivially_move_constructible::value
;
393 static_assert(compliant
|| std::is_trivially_move_constructible
<T
>::value
,
394 "Not compliant with std::is_trivially_move_constructible; "
395 "Standard: false, Implementation: true");
396 static_assert(compliant
|| !std::is_trivially_move_constructible
<T
>::value
,
397 "Not compliant with std::is_trivially_move_constructible; "
398 "Standard: true, Implementation: false");
399 #endif // OTABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE
402 // is_trivially_copy_constructible()
404 // Determines whether the passed type `T` is trivially copy constructible.
406 // This metafunction is designed to be a drop-in replacement for the C++11
407 // `std::is_trivially_copy_constructible()` metafunction for platforms that have
408 // incomplete C++11 support (such as libstdc++ 4.x). On any platforms that do
409 // fully support C++11, we check whether this yields the same result as the std
412 // NOTE: `T obj(declval<const T&>());` needs to be well-formed and not call any
413 // nontrivial operation. Nontrivially destructible types will cause the
414 // expression to be nontrivial.
415 template <typename T
>
416 struct is_trivially_copy_constructible
418 std::is_object
<T
>::value
&& !std::is_array
<T
>::value
,
419 type_traits_internal::IsTriviallyCopyConstructibleObject
<T
>,
420 std::is_lvalue_reference
<T
>>::type::type
{
421 #if defined(OTABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE) && \
423 OTABSL_META_INTERNAL_STD_CONSTRUCTION_TRAITS_DONT_CHECK_DESTRUCTION)
425 static constexpr bool compliant
=
426 std::is_trivially_copy_constructible
<T
>::value
==
427 is_trivially_copy_constructible::value
;
428 static_assert(compliant
|| std::is_trivially_copy_constructible
<T
>::value
,
429 "Not compliant with std::is_trivially_copy_constructible; "
430 "Standard: false, Implementation: true");
431 static_assert(compliant
|| !std::is_trivially_copy_constructible
<T
>::value
,
432 "Not compliant with std::is_trivially_copy_constructible; "
433 "Standard: true, Implementation: false");
434 #endif // OTABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE
437 // is_trivially_move_assignable()
439 // Determines whether the passed type `T` is trivially move assignable.
441 // This metafunction is designed to be a drop-in replacement for the C++11
442 // `std::is_trivially_move_assignable()` metafunction for platforms that have
443 // incomplete C++11 support (such as libstdc++ 4.x). On any platforms that do
444 // fully support C++11, we check whether this yields the same result as the std
447 // NOTE: `is_assignable<T, U>::value` is `true` if the expression
448 // `declval<T>() = declval<U>()` is well-formed when treated as an unevaluated
449 // operand. `is_trivially_assignable<T, U>` requires the assignment to call no
450 // operation that is not trivial. `is_trivially_copy_assignable<T>` is simply
451 // `is_trivially_assignable<T&, T>`.
452 template <typename T
>
453 struct is_trivially_move_assignable
455 std::is_object
<T
>::value
&& !std::is_array
<T
>::value
&&
456 std::is_move_assignable
<T
>::value
,
457 std::is_move_assignable
<type_traits_internal::SingleMemberUnion
<T
>>,
458 type_traits_internal::IsTriviallyMoveAssignableReference
<T
>>::type::
460 #ifdef OTABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE
462 static constexpr bool compliant
=
463 std::is_trivially_move_assignable
<T
>::value
==
464 is_trivially_move_assignable::value
;
465 static_assert(compliant
|| std::is_trivially_move_assignable
<T
>::value
,
466 "Not compliant with std::is_trivially_move_assignable; "
467 "Standard: false, Implementation: true");
468 static_assert(compliant
|| !std::is_trivially_move_assignable
<T
>::value
,
469 "Not compliant with std::is_trivially_move_assignable; "
470 "Standard: true, Implementation: false");
471 #endif // OTABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE
474 // is_trivially_copy_assignable()
476 // Determines whether the passed type `T` is trivially copy assignable.
478 // This metafunction is designed to be a drop-in replacement for the C++11
479 // `std::is_trivially_copy_assignable()` metafunction for platforms that have
480 // incomplete C++11 support (such as libstdc++ 4.x). On any platforms that do
481 // fully support C++11, we check whether this yields the same result as the std
484 // NOTE: `is_assignable<T, U>::value` is `true` if the expression
485 // `declval<T>() = declval<U>()` is well-formed when treated as an unevaluated
486 // operand. `is_trivially_assignable<T, U>` requires the assignment to call no
487 // operation that is not trivial. `is_trivially_copy_assignable<T>` is simply
488 // `is_trivially_assignable<T&, const T&>`.
489 template <typename T
>
490 struct is_trivially_copy_assignable
491 : std::integral_constant
<
492 bool, __has_trivial_assign(typename
std::remove_reference
<T
>::type
) &&
493 absl::is_copy_assignable
<T
>::value
> {
494 #ifdef OTABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE
496 static constexpr bool compliant
=
497 std::is_trivially_copy_assignable
<T
>::value
==
498 is_trivially_copy_assignable::value
;
499 static_assert(compliant
|| std::is_trivially_copy_assignable
<T
>::value
,
500 "Not compliant with std::is_trivially_copy_assignable; "
501 "Standard: false, Implementation: true");
502 static_assert(compliant
|| !std::is_trivially_copy_assignable
<T
>::value
,
503 "Not compliant with std::is_trivially_copy_assignable; "
504 "Standard: true, Implementation: false");
505 #endif // OTABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE
508 namespace type_traits_internal
{
509 // is_trivially_copyable()
511 // Determines whether the passed type `T` is trivially copyable.
513 // This metafunction is designed to be a drop-in replacement for the C++11
514 // `std::is_trivially_copyable()` metafunction for platforms that have
515 // incomplete C++11 support (such as libstdc++ 4.x). We use the C++17 definition
516 // of TriviallyCopyable.
518 // NOTE: `is_trivially_copyable<T>::value` is `true` if all of T's copy/move
519 // constructors/assignment operators are trivial or deleted, T has at least
520 // one non-deleted copy/move constructor/assignment operator, and T is trivially
521 // destructible. Arrays of trivially copyable types are trivially copyable.
523 // We expose this metafunction only for internal use within absl.
524 template <typename T
>
525 class is_trivially_copyable_impl
{
526 using ExtentsRemoved
= typename
std::remove_all_extents
<T
>::type
;
527 static constexpr bool kIsCopyOrMoveConstructible
=
528 std::is_copy_constructible
<ExtentsRemoved
>::value
||
529 std::is_move_constructible
<ExtentsRemoved
>::value
;
530 static constexpr bool kIsCopyOrMoveAssignable
=
531 absl::is_copy_assignable
<ExtentsRemoved
>::value
||
532 absl::is_move_assignable
<ExtentsRemoved
>::value
;
535 static constexpr bool kValue
=
536 (__has_trivial_copy(ExtentsRemoved
) || !kIsCopyOrMoveConstructible
) &&
537 (__has_trivial_assign(ExtentsRemoved
) || !kIsCopyOrMoveAssignable
) &&
538 (kIsCopyOrMoveConstructible
|| kIsCopyOrMoveAssignable
) &&
539 is_trivially_destructible
<ExtentsRemoved
>::value
&&
540 // We need to check for this explicitly because otherwise we'll say
541 // references are trivial copyable when compiled by MSVC.
542 !std::is_reference
<ExtentsRemoved
>::value
;
545 template <typename T
>
546 struct is_trivially_copyable
547 : std::integral_constant
<
548 bool, type_traits_internal::is_trivially_copyable_impl
<T
>::kValue
> {};
549 } // namespace type_traits_internal
551 // -----------------------------------------------------------------------------
552 // C++14 "_t" trait aliases
553 // -----------------------------------------------------------------------------
555 template <typename T
>
556 using remove_cv_t
= typename
std::remove_cv
<T
>::type
;
558 template <typename T
>
559 using remove_const_t
= typename
std::remove_const
<T
>::type
;
561 template <typename T
>
562 using remove_volatile_t
= typename
std::remove_volatile
<T
>::type
;
564 template <typename T
>
565 using add_cv_t
= typename
std::add_cv
<T
>::type
;
567 template <typename T
>
568 using add_const_t
= typename
std::add_const
<T
>::type
;
570 template <typename T
>
571 using add_volatile_t
= typename
std::add_volatile
<T
>::type
;
573 template <typename T
>
574 using remove_reference_t
= typename
std::remove_reference
<T
>::type
;
576 template <typename T
>
577 using add_lvalue_reference_t
= typename
std::add_lvalue_reference
<T
>::type
;
579 template <typename T
>
580 using add_rvalue_reference_t
= typename
std::add_rvalue_reference
<T
>::type
;
582 template <typename T
>
583 using remove_pointer_t
= typename
std::remove_pointer
<T
>::type
;
585 template <typename T
>
586 using add_pointer_t
= typename
std::add_pointer
<T
>::type
;
588 template <typename T
>
589 using make_signed_t
= typename
std::make_signed
<T
>::type
;
591 template <typename T
>
592 using make_unsigned_t
= typename
std::make_unsigned
<T
>::type
;
594 template <typename T
>
595 using remove_extent_t
= typename
std::remove_extent
<T
>::type
;
597 template <typename T
>
598 using remove_all_extents_t
= typename
std::remove_all_extents
<T
>::type
;
600 template <size_t Len
, size_t Align
= type_traits_internal::
601 default_alignment_of_aligned_storage
<Len
>::value
>
602 using aligned_storage_t
= typename
std::aligned_storage
<Len
, Align
>::type
;
604 template <typename T
>
605 using decay_t
= typename
std::decay
<T
>::type
;
607 template <bool B
, typename T
= void>
608 using enable_if_t
= typename
std::enable_if
<B
, T
>::type
;
610 template <bool B
, typename T
, typename F
>
611 using conditional_t
= typename
std::conditional
<B
, T
, F
>::type
;
613 template <typename
... T
>
614 using common_type_t
= typename
std::common_type
<T
...>::type
;
616 template <typename T
>
617 using underlying_type_t
= typename
std::underlying_type
<T
>::type
;
619 namespace type_traits_internal
{
621 #if __cplusplus >= 201703L
622 // std::result_of is deprecated (C++17) or removed (C++20)
623 template<typename
> struct result_of
;
624 template<typename F
, typename
... Args
>
625 struct result_of
<F(Args
...)> : std::invoke_result
<F
, Args
...> {};
627 template<typename F
> using result_of
= std::result_of
<F
>;
630 } // namespace type_traits_internal
633 using result_of_t
= typename
type_traits_internal::result_of
<F
>::type
;
635 namespace type_traits_internal
{
636 // In MSVC we can't probe std::hash or stdext::hash because it triggers a
637 // static_assert instead of failing substitution. Libc++ prior to 4.0
638 // also used a static_assert.
640 #if defined(_MSC_VER) || (defined(_LIBCPP_VERSION) && \
641 _LIBCPP_VERSION < 4000 && _LIBCPP_STD_VER > 11)
642 #define OTABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_ 0
644 #define OTABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_ 1
647 #if !OTABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
648 template <typename Key
, typename
= size_t>
649 struct IsHashable
: std::true_type
{};
650 #else // OTABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
651 template <typename Key
, typename
= void>
652 struct IsHashable
: std::false_type
{};
654 template <typename Key
>
657 absl::enable_if_t
<std::is_convertible
<
658 decltype(std::declval
<std::hash
<Key
>&>()(std::declval
<Key
const&>())),
659 std::size_t>::value
>> : std::true_type
{};
660 #endif // !OTABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
662 struct AssertHashEnabledHelper
{
664 static void Sink(...) {}
668 static auto GetReturnType(int)
669 -> decltype(std::declval
<std::hash
<Key
>>()(std::declval
<Key
const&>()));
671 static NAT
GetReturnType(...);
674 static std::nullptr_t
DoIt() {
675 static_assert(IsHashable
<Key
>::value
,
676 "std::hash<Key> does not provide a call operator");
678 std::is_default_constructible
<std::hash
<Key
>>::value
,
679 "std::hash<Key> must be default constructible when it is enabled");
681 std::is_copy_constructible
<std::hash
<Key
>>::value
,
682 "std::hash<Key> must be copy constructible when it is enabled");
683 static_assert(absl::is_copy_assignable
<std::hash
<Key
>>::value
,
684 "std::hash<Key> must be copy assignable when it is enabled");
685 // is_destructible is unchecked as it's implied by each of the
686 // is_constructible checks.
687 using ReturnType
= decltype(GetReturnType
<Key
>(0));
688 static_assert(std::is_same
<ReturnType
, NAT
>::value
||
689 std::is_same
<ReturnType
, size_t>::value
,
690 "std::hash<Key> must return size_t");
694 template <class... Ts
>
695 friend void AssertHashEnabled();
698 template <class... Ts
>
699 inline void AssertHashEnabled() {
700 using Helper
= AssertHashEnabledHelper
;
701 Helper::Sink(Helper::DoIt
<Ts
>()...);
704 } // namespace type_traits_internal
706 // An internal namespace that is required to implement the C++17 swap traits.
707 // It is not further nested in type_traits_internal to avoid long symbol names.
708 namespace swap_internal
{
710 // Necessary for the traits.
713 // This declaration prevents global `swap` and `absl::swap` overloads from being
714 // considered unless ADL picks them up.
718 using IsSwappableImpl
= decltype(swap(std::declval
<T
&>(), std::declval
<T
&>()));
720 // NOTE: This dance with the default template parameter is for MSVC.
722 class IsNoexcept
= std::integral_constant
<
723 bool, noexcept(swap(std::declval
<T
&>(), std::declval
<T
&>()))>>
724 using IsNothrowSwappableImpl
= typename
std::enable_if
<IsNoexcept::value
>::type
;
728 // Determines whether the standard swap idiom is a valid expression for
729 // arguments of type `T`.
732 : absl::type_traits_internal::is_detected
<IsSwappableImpl
, T
> {};
734 // IsNothrowSwappable
736 // Determines whether the standard swap idiom is a valid expression for
737 // arguments of type `T` and is noexcept.
739 struct IsNothrowSwappable
740 : absl::type_traits_internal::is_detected
<IsNothrowSwappableImpl
, T
> {};
744 // Performs the swap idiom from a namespace where valid candidates may only be
745 // found in `std` or via ADL.
746 template <class T
, absl::enable_if_t
<IsSwappable
<T
>::value
, int> = 0>
747 void Swap(T
& lhs
, T
& rhs
) noexcept(IsNothrowSwappable
<T
>::value
) {
751 // StdSwapIsUnconstrained
753 // Some standard library implementations are broken in that they do not
754 // constrain `std::swap`. This will effectively tell us if we are dealing with
755 // one of those implementations.
756 using StdSwapIsUnconstrained
= IsSwappable
<void()>;
758 } // namespace swap_internal
760 namespace type_traits_internal
{
762 // Make the swap-related traits/function accessible from this namespace.
763 using swap_internal::IsNothrowSwappable
;
764 using swap_internal::IsSwappable
;
765 using swap_internal::Swap
;
766 using swap_internal::StdSwapIsUnconstrained
;
768 } // namespace type_traits_internal
772 #endif // OTABSL_META_TYPE_TRAITS_H_