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
44namespace absl {
45
46// Defined and documented later on in this file.
47template <typename T>
48struct is_trivially_move_assignable;
49
50namespace 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
58template <class T>
59union SingleMemberUnion {
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
68template <class T>
69struct IsTriviallyMoveAssignableReference : std::false_type {};
70
71template <class T>
72struct IsTriviallyMoveAssignableReference<T&>
73 : absl::is_trivially_move_assignable<T>::type {};
74
75template <class T>
76struct IsTriviallyMoveAssignableReference<T&&>
77 : absl::is_trivially_move_assignable<T>::type {};
78
79template <typename... Ts>
80struct 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.
87template <size_t Len, typename T = std::aligned_storage<Len>>
88struct default_alignment_of_aligned_storage;
89
90template <size_t Len, size_t Align>
91struct default_alignment_of_aligned_storage<Len,
92 std::aligned_storage<Len, Align>> {
93 static constexpr size_t value = Align;
94};
95
96////////////////////////////////
97// Library Fundamentals V2 TS //
98////////////////////////////////
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
110template <class Enabler, template <class...> class Op, class... Args>
111struct is_detected_impl {
112 using type = std::false_type;
113};
114
115template <template <class...> class Op, class... Args>
116struct is_detected_impl<typename VoidTImpl<Op<Args...>>::type, Op, Args...> {
117 using type = std::true_type;
118};
119
120template <template <class...> class Op, class... Args>
121struct is_detected : is_detected_impl<void, Op, Args...>::type {};
122
123template <class Enabler, class To, template <class...> class Op, class... Args>
124struct is_detected_convertible_impl {
125 using type = std::false_type;
126};
127
128template <class To, template <class...> class Op, class... Args>
129struct is_detected_convertible_impl<
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
135template <class To, template <class...> class Op, class... Args>
136struct is_detected_convertible
137 : is_detected_convertible_impl<void, To, Op, Args...>::type {};
138
139template <typename T>
140using IsCopyAssignableImpl =
141 decltype(std::declval<T&>() = std::declval<const T&>());
142
143template <typename T>
144using IsMoveAssignableImpl = decltype(std::declval<T&>() = std::declval<T&&>());
145
146} // namespace type_traits_internal
147
148template <typename T>
149struct is_copy_assignable : type_traits_internal::is_detected<
150 type_traits_internal::IsCopyAssignableImpl, T> {
151};
152
153template <typename T>
154struct is_move_assignable : type_traits_internal::is_detected<
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.
170template <typename... Ts>
171using 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.
182template <typename... Ts>
183struct conjunction;
184
185template <typename T, typename... Ts>
186struct conjunction<T, Ts...>
187 : std::conditional<T::value, conjunction<Ts...>, T>::type {};
188
189template <typename T>
190struct conjunction<T> : T {};
191
192template <>
193struct 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.
204template <typename... Ts>
205struct disjunction;
206
207template <typename T, typename... Ts>
208struct disjunction<T, Ts...> :
209 std::conditional<T::value, T, disjunction<Ts...>>::type {};
210
211template <typename T>
212struct disjunction<T> : T {};
213
214template <>
215struct 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.
224template <typename T>
225struct 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.
241template <typename T>
242struct is_trivially_destructible
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 ==
248 is_trivially_destructible::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.
290template <typename T>
291struct is_trivially_default_constructible
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 =
298 std::is_trivially_default_constructible<T>::value ==
299 is_trivially_default_constructible::value;
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.
322template <typename T>
323struct is_trivially_move_constructible
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 =
332 std::is_trivially_move_constructible<T>::value ==
333 is_trivially_move_constructible::value;
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.
356template <typename T>
357struct is_trivially_copy_constructible
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 =
366 std::is_trivially_copy_constructible<T>::value ==
367 is_trivially_copy_constructible::value;
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>`.
392template <typename T>
393struct is_trivially_move_assignable
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 =
402 std::is_trivially_move_assignable<T>::value ==
403 is_trivially_move_assignable::value;
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&>`.
428template <typename T>
429struct is_trivially_copy_assignable
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 =
436 std::is_trivially_copy_assignable<T>::value ==
437 is_trivially_copy_assignable::value;
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
447namespace 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.
463template <typename T>
464class is_trivially_copyable_impl {
465 using ExtentsRemoved = typename std::remove_all_extents<T>::type;
466 static constexpr bool kIsCopyOrMoveConstructible =
467 std::is_copy_constructible<ExtentsRemoved>::value ||
468 std::is_move_constructible<ExtentsRemoved>::value;
469 static constexpr bool kIsCopyOrMoveAssignable =
470 absl::is_copy_assignable<ExtentsRemoved>::value ||
471 absl::is_move_assignable<ExtentsRemoved>::value;
472
473 public:
474 static constexpr bool kValue =
475 (__has_trivial_copy(ExtentsRemoved) || !kIsCopyOrMoveConstructible) &&
476 (__has_trivial_assign(ExtentsRemoved) || !kIsCopyOrMoveAssignable) &&
477 (kIsCopyOrMoveConstructible || kIsCopyOrMoveAssignable) &&
478 is_trivially_destructible<ExtentsRemoved>::value &&
479 // We need to check for this explicitly because otherwise we'll say
480 // references are trivial copyable when compiled by MSVC.
481 !std::is_reference<ExtentsRemoved>::value;
482};
483
484template <typename T>
485struct is_trivially_copyable
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
494template <typename T>
495using remove_cv_t = typename std::remove_cv<T>::type;
496
497template <typename T>
498using remove_const_t = typename std::remove_const<T>::type;
499
500template <typename T>
501using remove_volatile_t = typename std::remove_volatile<T>::type;
502
503template <typename T>
504using add_cv_t = typename std::add_cv<T>::type;
505
506template <typename T>
507using add_const_t = typename std::add_const<T>::type;
508
509template <typename T>
510using add_volatile_t = typename std::add_volatile<T>::type;
511
512template <typename T>
513using remove_reference_t = typename std::remove_reference<T>::type;
514
515template <typename T>
516using add_lvalue_reference_t = typename std::add_lvalue_reference<T>::type;
517
518template <typename T>
519using add_rvalue_reference_t = typename std::add_rvalue_reference<T>::type;
520
521template <typename T>
522using remove_pointer_t = typename std::remove_pointer<T>::type;
523
524template <typename T>
525using add_pointer_t = typename std::add_pointer<T>::type;
526
527template <typename T>
528using make_signed_t = typename std::make_signed<T>::type;
529
530template <typename T>
531using make_unsigned_t = typename std::make_unsigned<T>::type;
532
533template <typename T>
534using remove_extent_t = typename std::remove_extent<T>::type;
535
536template <typename T>
537using remove_all_extents_t = typename std::remove_all_extents<T>::type;
538
539template <size_t Len, size_t Align = type_traits_internal::
540 default_alignment_of_aligned_storage<Len>::value>
541using aligned_storage_t = typename std::aligned_storage<Len, Align>::type;
542
543template <typename T>
544using decay_t = typename std::decay<T>::type;
545
546template <bool B, typename T = void>
547using enable_if_t = typename std::enable_if<B, T>::type;
548
549template <bool B, typename T, typename F>
550using conditional_t = typename std::conditional<B, T, F>::type;
551
552template <typename... T>
553using common_type_t = typename std::common_type<T...>::type;
554
555template <typename T>
556using underlying_type_t = typename std::underlying_type<T>::type;
557
558template <typename T>
559using result_of_t = typename std::result_of<T>::type;
560
561namespace 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_
574template <typename Key, typename = size_t>
575struct IsHashable : std::true_type {};
576#else // ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
577template <typename Key, typename = void>
578struct IsHashable : std::false_type {};
579
580template <typename Key>
581struct 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
588struct AssertHashEnabledHelper {
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 ||
615 std::is_same<ReturnType, size_t>::value,
616 "std::hash<Key> must return size_t");
617 return nullptr;
618 }
619
620 template <class... Ts>
621 friend void AssertHashEnabled();
622};
623
624template <class... Ts>
625inline 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.
634namespace swap_internal {
635
636// Necessary for the traits.
637using std::swap;
638
639// This declaration prevents global `swap` and `absl::swap` overloads from being
640// considered unless ADL picks them up.
641void swap();
642
643template <class T>
644using IsSwappableImpl = decltype(swap(std::declval<T&>(), std::declval<T&>()));
645
646// NOTE: This dance with the default template parameter is for MSVC.
647template <class T,
648 class IsNoexcept = std::integral_constant<
649 bool, noexcept(swap(std::declval<T&>(), std::declval<T&>()))>>
650using 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`.
656template <class T>
657struct IsSwappable
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.
664template <class T>
665struct IsNothrowSwappable
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.
672template <class T, absl::enable_if_t<IsSwappable<T>::value, int> = 0>
673void 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.
682using StdSwapIsUnconstrained = IsSwappable<void()>;
683
684} // namespace swap_internal
685
686namespace type_traits_internal {
687
688// Make the swap-related traits/function accessible from this namespace.
689using swap_internal::IsNothrowSwappable;
690using swap_internal::IsSwappable;
691using swap_internal::Swap;
692using swap_internal::StdSwapIsUnconstrained;
693
694} // namespace type_traits_internal
695} // namespace absl
696
697#endif // ABSL_META_TYPE_TRAITS_H_
698