type_traits.h
Go to the documentation of this file.
00001 //
00002 // Copyright 2017 The Abseil Authors.
00003 //
00004 // Licensed under the Apache License, Version 2.0 (the "License");
00005 // you may not use this file except in compliance with the License.
00006 // You may obtain a copy of the License at
00007 //
00008 //      https://www.apache.org/licenses/LICENSE-2.0
00009 //
00010 // Unless required by applicable law or agreed to in writing, software
00011 // distributed under the License is distributed on an "AS IS" BASIS,
00012 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013 // See the License for the specific language governing permissions and
00014 // limitations under the License.
00015 //
00016 // -----------------------------------------------------------------------------
00017 // type_traits.h
00018 // -----------------------------------------------------------------------------
00019 //
00020 // This file contains C++11-compatible versions of standard <type_traits> API
00021 // functions for determining the characteristics of types. Such traits can
00022 // support type inference, classification, and transformation, as well as
00023 // make it easier to write templates based on generic type behavior.
00024 //
00025 // See https://en.cppreference.com/w/cpp/header/type_traits
00026 //
00027 // WARNING: use of many of the constructs in this header will count as "complex
00028 // template metaprogramming", so before proceeding, please carefully consider
00029 // https://google.github.io/styleguide/cppguide.html#Template_metaprogramming
00030 //
00031 // WARNING: using template metaprogramming to detect or depend on API
00032 // features is brittle and not guaranteed. Neither the standard library nor
00033 // Abseil provides any guarantee that APIs are stable in the face of template
00034 // metaprogramming. Use with caution.
00035 #ifndef ABSL_META_TYPE_TRAITS_H_
00036 #define ABSL_META_TYPE_TRAITS_H_
00037 
00038 #include <stddef.h>
00039 #include <functional>
00040 #include <type_traits>
00041 
00042 #include "absl/base/config.h"
00043 
00044 namespace absl {
00045 
00046 // Defined and documented later on in this file.
00047 template <typename T>
00048 struct is_trivially_move_assignable;
00049 
00050 namespace type_traits_internal {
00051 
00052 // Silence MSVC warnings about the destructor being defined as deleted.
00053 #if defined(_MSC_VER) && !defined(__GNUC__)
00054 #pragma warning(push)
00055 #pragma warning(disable : 4624)
00056 #endif  // defined(_MSC_VER) && !defined(__GNUC__)
00057 
00058 template <class T>
00059 union SingleMemberUnion {
00060   T t;
00061 };
00062 
00063 // Restore the state of the destructor warning that was silenced above.
00064 #if defined(_MSC_VER) && !defined(__GNUC__)
00065 #pragma warning(pop)
00066 #endif  // defined(_MSC_VER) && !defined(__GNUC__)
00067 
00068 template <class T>
00069 struct IsTriviallyMoveAssignableReference : std::false_type {};
00070 
00071 template <class T>
00072 struct IsTriviallyMoveAssignableReference<T&>
00073     : absl::is_trivially_move_assignable<T>::type {};
00074 
00075 template <class T>
00076 struct IsTriviallyMoveAssignableReference<T&&>
00077     : absl::is_trivially_move_assignable<T>::type {};
00078 
00079 template <typename... Ts>
00080 struct VoidTImpl {
00081   using type = void;
00082 };
00083 
00084 // This trick to retrieve a default alignment is necessary for our
00085 // implementation of aligned_storage_t to be consistent with any implementation
00086 // of std::aligned_storage.
00087 template <size_t Len, typename T = std::aligned_storage<Len>>
00088 struct default_alignment_of_aligned_storage;
00089 
00090 template <size_t Len, size_t Align>
00091 struct default_alignment_of_aligned_storage<Len,
00092                                             std::aligned_storage<Len, Align>> {
00093   static constexpr size_t value = Align;
00094 };
00095 
00097 // Library Fundamentals V2 TS //
00099 
00100 // NOTE: The `is_detected` family of templates here differ from the library
00101 // fundamentals specification in that for library fundamentals, `Op<Args...>` is
00102 // evaluated as soon as the type `is_detected<Op, Args...>` undergoes
00103 // substitution, regardless of whether or not the `::value` is accessed. That
00104 // is inconsistent with all other standard traits and prevents lazy evaluation
00105 // in larger contexts (such as if the `is_detected` check is a trailing argument
00106 // of a `conjunction`. This implementation opts to instead be lazy in the same
00107 // way that the standard traits are (this "defect" of the detection idiom
00108 // specifications has been reported).
00109 
00110 template <class Enabler, template <class...> class Op, class... Args>
00111 struct is_detected_impl {
00112   using type = std::false_type;
00113 };
00114 
00115 template <template <class...> class Op, class... Args>
00116 struct is_detected_impl<typename VoidTImpl<Op<Args...>>::type, Op, Args...> {
00117   using type = std::true_type;
00118 };
00119 
00120 template <template <class...> class Op, class... Args>
00121 struct is_detected : is_detected_impl<void, Op, Args...>::type {};
00122 
00123 template <class Enabler, class To, template <class...> class Op, class... Args>
00124 struct is_detected_convertible_impl {
00125   using type = std::false_type;
00126 };
00127 
00128 template <class To, template <class...> class Op, class... Args>
00129 struct is_detected_convertible_impl<
00130     typename std::enable_if<std::is_convertible<Op<Args...>, To>::value>::type,
00131     To, Op, Args...> {
00132   using type = std::true_type;
00133 };
00134 
00135 template <class To, template <class...> class Op, class... Args>
00136 struct is_detected_convertible
00137     : is_detected_convertible_impl<void, To, Op, Args...>::type {};
00138 
00139 template <typename T>
00140 using IsCopyAssignableImpl =
00141     decltype(std::declval<T&>() = std::declval<const T&>());
00142 
00143 template <typename T>
00144 using IsMoveAssignableImpl = decltype(std::declval<T&>() = std::declval<T&&>());
00145 
00146 }  // namespace type_traits_internal
00147 
00148 template <typename T>
00149 struct is_copy_assignable : type_traits_internal::is_detected<
00150                                 type_traits_internal::IsCopyAssignableImpl, T> {
00151 };
00152 
00153 template <typename T>
00154 struct is_move_assignable : type_traits_internal::is_detected<
00155                                 type_traits_internal::IsMoveAssignableImpl, T> {
00156 };
00157 
00158 // void_t()
00159 //
00160 // Ignores the type of any its arguments and returns `void`. In general, this
00161 // metafunction allows you to create a general case that maps to `void` while
00162 // allowing specializations that map to specific types.
00163 //
00164 // This metafunction is designed to be a drop-in replacement for the C++17
00165 // `std::void_t` metafunction.
00166 //
00167 // NOTE: `absl::void_t` does not use the standard-specified implementation so
00168 // that it can remain compatible with gcc < 5.1. This can introduce slightly
00169 // different behavior, such as when ordering partial specializations.
00170 template <typename... Ts>
00171 using void_t = typename type_traits_internal::VoidTImpl<Ts...>::type;
00172 
00173 // conjunction
00174 //
00175 // Performs a compile-time logical AND operation on the passed types (which
00176 // must have  `::value` members convertible to `bool`. Short-circuits if it
00177 // encounters any `false` members (and does not compare the `::value` members
00178 // of any remaining arguments).
00179 //
00180 // This metafunction is designed to be a drop-in replacement for the C++17
00181 // `std::conjunction` metafunction.
00182 template <typename... Ts>
00183 struct conjunction;
00184 
00185 template <typename T, typename... Ts>
00186 struct conjunction<T, Ts...>
00187     : std::conditional<T::value, conjunction<Ts...>, T>::type {};
00188 
00189 template <typename T>
00190 struct conjunction<T> : T {};
00191 
00192 template <>
00193 struct conjunction<> : std::true_type {};
00194 
00195 // disjunction
00196 //
00197 // Performs a compile-time logical OR operation on the passed types (which
00198 // must have  `::value` members convertible to `bool`. Short-circuits if it
00199 // encounters any `true` members (and does not compare the `::value` members
00200 // of any remaining arguments).
00201 //
00202 // This metafunction is designed to be a drop-in replacement for the C++17
00203 // `std::disjunction` metafunction.
00204 template <typename... Ts>
00205 struct disjunction;
00206 
00207 template <typename T, typename... Ts>
00208 struct disjunction<T, Ts...> :
00209       std::conditional<T::value, T, disjunction<Ts...>>::type {};
00210 
00211 template <typename T>
00212 struct disjunction<T> : T {};
00213 
00214 template <>
00215 struct disjunction<> : std::false_type {};
00216 
00217 // negation
00218 //
00219 // Performs a compile-time logical NOT operation on the passed type (which
00220 // must have  `::value` members convertible to `bool`.
00221 //
00222 // This metafunction is designed to be a drop-in replacement for the C++17
00223 // `std::negation` metafunction.
00224 template <typename T>
00225 struct negation : std::integral_constant<bool, !T::value> {};
00226 
00227 // is_trivially_destructible()
00228 //
00229 // Determines whether the passed type `T` is trivially destructable.
00230 //
00231 // This metafunction is designed to be a drop-in replacement for the C++11
00232 // `std::is_trivially_destructible()` metafunction for platforms that have
00233 // incomplete C++11 support (such as libstdc++ 4.x). On any platforms that do
00234 // fully support C++11, we check whether this yields the same result as the std
00235 // implementation.
00236 //
00237 // NOTE: the extensions (__has_trivial_xxx) are implemented in gcc (version >=
00238 // 4.3) and clang. Since we are supporting libstdc++ > 4.7, they should always
00239 // be present. These  extensions are documented at
00240 // https://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html#Type-Traits.
00241 template <typename T>
00242 struct is_trivially_destructible
00243     : std::integral_constant<bool, __has_trivial_destructor(T) &&
00244                                    std::is_destructible<T>::value> {
00245 #ifdef ABSL_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE
00246  private:
00247   static constexpr bool compliant = std::is_trivially_destructible<T>::value ==
00248                                     is_trivially_destructible::value;
00249   static_assert(compliant || std::is_trivially_destructible<T>::value,
00250                 "Not compliant with std::is_trivially_destructible; "
00251                 "Standard: false, Implementation: true");
00252   static_assert(compliant || !std::is_trivially_destructible<T>::value,
00253                 "Not compliant with std::is_trivially_destructible; "
00254                 "Standard: true, Implementation: false");
00255 #endif  // ABSL_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE
00256 };
00257 
00258 // is_trivially_default_constructible()
00259 //
00260 // Determines whether the passed type `T` is trivially default constructible.
00261 //
00262 // This metafunction is designed to be a drop-in replacement for the C++11
00263 // `std::is_trivially_default_constructible()` metafunction for platforms that
00264 // have incomplete C++11 support (such as libstdc++ 4.x). On any platforms that
00265 // do fully support C++11, we check whether this yields the same result as the
00266 // std implementation.
00267 //
00268 // NOTE: according to the C++ standard, Section: 20.15.4.3 [meta.unary.prop]
00269 // "The predicate condition for a template specialization is_constructible<T,
00270 // Args...> shall be satisfied if and only if the following variable
00271 // definition would be well-formed for some invented variable t:
00272 //
00273 // T t(declval<Args>()...);
00274 //
00275 // is_trivially_constructible<T, Args...> additionally requires that the
00276 // variable definition does not call any operation that is not trivial.
00277 // For the purposes of this check, the call to std::declval is considered
00278 // trivial."
00279 //
00280 // Notes from https://en.cppreference.com/w/cpp/types/is_constructible:
00281 // In many implementations, is_nothrow_constructible also checks if the
00282 // destructor throws because it is effectively noexcept(T(arg)). Same
00283 // applies to is_trivially_constructible, which, in these implementations, also
00284 // requires that the destructor is trivial.
00285 // GCC bug 51452: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51452
00286 // LWG issue 2116: http://cplusplus.github.io/LWG/lwg-active.html#2116.
00287 //
00288 // "T obj();" need to be well-formed and not call any nontrivial operation.
00289 // Nontrivially destructible types will cause the expression to be nontrivial.
00290 template <typename T>
00291 struct is_trivially_default_constructible
00292     : std::integral_constant<bool, __has_trivial_constructor(T) &&
00293                                    std::is_default_constructible<T>::value &&
00294                                    is_trivially_destructible<T>::value> {
00295 #ifdef ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE
00296  private:
00297   static constexpr bool compliant =
00298       std::is_trivially_default_constructible<T>::value ==
00299       is_trivially_default_constructible::value;
00300   static_assert(compliant || std::is_trivially_default_constructible<T>::value,
00301                 "Not compliant with std::is_trivially_default_constructible; "
00302                 "Standard: false, Implementation: true");
00303   static_assert(compliant || !std::is_trivially_default_constructible<T>::value,
00304                 "Not compliant with std::is_trivially_default_constructible; "
00305                 "Standard: true, Implementation: false");
00306 #endif  // ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE
00307 };
00308 
00309 // is_trivially_move_constructible()
00310 //
00311 // Determines whether the passed type `T` is trivially move constructible.
00312 //
00313 // This metafunction is designed to be a drop-in replacement for the C++11
00314 // `std::is_trivially_move_constructible()` metafunction for platforms that have
00315 // incomplete C++11 support (such as libstdc++ 4.x). On any platforms that do
00316 // fully support C++11, we check whether this yields the same result as the std
00317 // implementation.
00318 //
00319 // NOTE: `T obj(declval<T>());` needs to be well-formed and not call any
00320 // nontrivial operation.  Nontrivially destructible types will cause the
00321 // expression to be nontrivial.
00322 template <typename T>
00323 struct is_trivially_move_constructible
00324     : std::conditional<
00325           std::is_object<T>::value && !std::is_array<T>::value,
00326           std::is_move_constructible<
00327               type_traits_internal::SingleMemberUnion<T>>,
00328           std::is_reference<T>>::type::type {
00329 #ifdef ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE
00330  private:
00331   static constexpr bool compliant =
00332       std::is_trivially_move_constructible<T>::value ==
00333       is_trivially_move_constructible::value;
00334   static_assert(compliant || std::is_trivially_move_constructible<T>::value,
00335                 "Not compliant with std::is_trivially_move_constructible; "
00336                 "Standard: false, Implementation: true");
00337   static_assert(compliant || !std::is_trivially_move_constructible<T>::value,
00338                 "Not compliant with std::is_trivially_move_constructible; "
00339                 "Standard: true, Implementation: false");
00340 #endif  // ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE
00341 };
00342 
00343 // is_trivially_copy_constructible()
00344 //
00345 // Determines whether the passed type `T` is trivially copy constructible.
00346 //
00347 // This metafunction is designed to be a drop-in replacement for the C++11
00348 // `std::is_trivially_copy_constructible()` metafunction for platforms that have
00349 // incomplete C++11 support (such as libstdc++ 4.x). On any platforms that do
00350 // fully support C++11, we check whether this yields the same result as the std
00351 // implementation.
00352 //
00353 // NOTE: `T obj(declval<const T&>());` needs to be well-formed and not call any
00354 // nontrivial operation.  Nontrivially destructible types will cause the
00355 // expression to be nontrivial.
00356 template <typename T>
00357 struct is_trivially_copy_constructible
00358     : std::conditional<
00359           std::is_object<T>::value && !std::is_array<T>::value,
00360           std::is_copy_constructible<
00361               type_traits_internal::SingleMemberUnion<T>>,
00362           std::is_lvalue_reference<T>>::type::type {
00363 #ifdef ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE
00364  private:
00365   static constexpr bool compliant =
00366       std::is_trivially_copy_constructible<T>::value ==
00367       is_trivially_copy_constructible::value;
00368   static_assert(compliant || std::is_trivially_copy_constructible<T>::value,
00369                 "Not compliant with std::is_trivially_copy_constructible; "
00370                 "Standard: false, Implementation: true");
00371   static_assert(compliant || !std::is_trivially_copy_constructible<T>::value,
00372                 "Not compliant with std::is_trivially_copy_constructible; "
00373                 "Standard: true, Implementation: false");
00374 #endif  // ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE
00375 };
00376 
00377 // is_trivially_move_assignable()
00378 //
00379 // Determines whether the passed type `T` is trivially move assignable.
00380 //
00381 // This metafunction is designed to be a drop-in replacement for the C++11
00382 // `std::is_trivially_move_assignable()` metafunction for platforms that have
00383 // incomplete C++11 support (such as libstdc++ 4.x). On any platforms that do
00384 // fully support C++11, we check whether this yields the same result as the std
00385 // implementation.
00386 //
00387 // NOTE: `is_assignable<T, U>::value` is `true` if the expression
00388 // `declval<T>() = declval<U>()` is well-formed when treated as an unevaluated
00389 // operand. `is_trivially_assignable<T, U>` requires the assignment to call no
00390 // operation that is not trivial. `is_trivially_copy_assignable<T>` is simply
00391 // `is_trivially_assignable<T&, T>`.
00392 template <typename T>
00393 struct is_trivially_move_assignable
00394     : std::conditional<
00395           std::is_object<T>::value && !std::is_array<T>::value,
00396           std::is_move_assignable<type_traits_internal::SingleMemberUnion<T>>,
00397           type_traits_internal::IsTriviallyMoveAssignableReference<T>>::type::
00398           type {
00399 #ifdef ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE
00400  private:
00401   static constexpr bool compliant =
00402       std::is_trivially_move_assignable<T>::value ==
00403       is_trivially_move_assignable::value;
00404   static_assert(compliant || std::is_trivially_move_assignable<T>::value,
00405                 "Not compliant with std::is_trivially_move_assignable; "
00406                 "Standard: false, Implementation: true");
00407   static_assert(compliant || !std::is_trivially_move_assignable<T>::value,
00408                 "Not compliant with std::is_trivially_move_assignable; "
00409                 "Standard: true, Implementation: false");
00410 #endif  // ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE
00411 };
00412 
00413 // is_trivially_copy_assignable()
00414 //
00415 // Determines whether the passed type `T` is trivially copy assignable.
00416 //
00417 // This metafunction is designed to be a drop-in replacement for the C++11
00418 // `std::is_trivially_copy_assignable()` metafunction for platforms that have
00419 // incomplete C++11 support (such as libstdc++ 4.x). On any platforms that do
00420 // fully support C++11, we check whether this yields the same result as the std
00421 // implementation.
00422 //
00423 // NOTE: `is_assignable<T, U>::value` is `true` if the expression
00424 // `declval<T>() = declval<U>()` is well-formed when treated as an unevaluated
00425 // operand. `is_trivially_assignable<T, U>` requires the assignment to call no
00426 // operation that is not trivial. `is_trivially_copy_assignable<T>` is simply
00427 // `is_trivially_assignable<T&, const T&>`.
00428 template <typename T>
00429 struct is_trivially_copy_assignable
00430     : std::integral_constant<
00431           bool, __has_trivial_assign(typename std::remove_reference<T>::type) &&
00432                     absl::is_copy_assignable<T>::value> {
00433 #ifdef ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE
00434  private:
00435   static constexpr bool compliant =
00436       std::is_trivially_copy_assignable<T>::value ==
00437       is_trivially_copy_assignable::value;
00438   static_assert(compliant || std::is_trivially_copy_assignable<T>::value,
00439                 "Not compliant with std::is_trivially_copy_assignable; "
00440                 "Standard: false, Implementation: true");
00441   static_assert(compliant || !std::is_trivially_copy_assignable<T>::value,
00442                 "Not compliant with std::is_trivially_copy_assignable; "
00443                 "Standard: true, Implementation: false");
00444 #endif  // ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE
00445 };
00446 
00447 namespace type_traits_internal {
00448 // is_trivially_copyable()
00449 //
00450 // Determines whether the passed type `T` is trivially copyable.
00451 //
00452 // This metafunction is designed to be a drop-in replacement for the C++11
00453 // `std::is_trivially_copyable()` metafunction for platforms that have
00454 // incomplete C++11 support (such as libstdc++ 4.x). We use the C++17 definition
00455 // of TriviallyCopyable.
00456 //
00457 // NOTE: `is_trivially_copyable<T>::value` is `true` if all of T's copy/move
00458 // constructors/assignment operators are trivial or deleted, T has at least
00459 // one non-deleted copy/move constructor/assignment operator, and T is trivially
00460 // destructible. Arrays of trivially copyable types are trivially copyable.
00461 //
00462 // We expose this metafunction only for internal use within absl.
00463 template <typename T>
00464 class is_trivially_copyable_impl {
00465   using ExtentsRemoved = typename std::remove_all_extents<T>::type;
00466   static constexpr bool kIsCopyOrMoveConstructible =
00467       std::is_copy_constructible<ExtentsRemoved>::value ||
00468       std::is_move_constructible<ExtentsRemoved>::value;
00469   static constexpr bool kIsCopyOrMoveAssignable =
00470       absl::is_copy_assignable<ExtentsRemoved>::value ||
00471       absl::is_move_assignable<ExtentsRemoved>::value;
00472 
00473  public:
00474   static constexpr bool kValue =
00475       (__has_trivial_copy(ExtentsRemoved) || !kIsCopyOrMoveConstructible) &&
00476       (__has_trivial_assign(ExtentsRemoved) || !kIsCopyOrMoveAssignable) &&
00477       (kIsCopyOrMoveConstructible || kIsCopyOrMoveAssignable) &&
00478       is_trivially_destructible<ExtentsRemoved>::value &&
00479       // We need to check for this explicitly because otherwise we'll say
00480       // references are trivial copyable when compiled by MSVC.
00481       !std::is_reference<ExtentsRemoved>::value;
00482 };
00483 
00484 template <typename T>
00485 struct is_trivially_copyable
00486     : std::integral_constant<
00487           bool, type_traits_internal::is_trivially_copyable_impl<T>::kValue> {};
00488 }  // namespace type_traits_internal
00489 
00490 // -----------------------------------------------------------------------------
00491 // C++14 "_t" trait aliases
00492 // -----------------------------------------------------------------------------
00493 
00494 template <typename T>
00495 using remove_cv_t = typename std::remove_cv<T>::type;
00496 
00497 template <typename T>
00498 using remove_const_t = typename std::remove_const<T>::type;
00499 
00500 template <typename T>
00501 using remove_volatile_t = typename std::remove_volatile<T>::type;
00502 
00503 template <typename T>
00504 using add_cv_t = typename std::add_cv<T>::type;
00505 
00506 template <typename T>
00507 using add_const_t = typename std::add_const<T>::type;
00508 
00509 template <typename T>
00510 using add_volatile_t = typename std::add_volatile<T>::type;
00511 
00512 template <typename T>
00513 using remove_reference_t = typename std::remove_reference<T>::type;
00514 
00515 template <typename T>
00516 using add_lvalue_reference_t = typename std::add_lvalue_reference<T>::type;
00517 
00518 template <typename T>
00519 using add_rvalue_reference_t = typename std::add_rvalue_reference<T>::type;
00520 
00521 template <typename T>
00522 using remove_pointer_t = typename std::remove_pointer<T>::type;
00523 
00524 template <typename T>
00525 using add_pointer_t = typename std::add_pointer<T>::type;
00526 
00527 template <typename T>
00528 using make_signed_t = typename std::make_signed<T>::type;
00529 
00530 template <typename T>
00531 using make_unsigned_t = typename std::make_unsigned<T>::type;
00532 
00533 template <typename T>
00534 using remove_extent_t = typename std::remove_extent<T>::type;
00535 
00536 template <typename T>
00537 using remove_all_extents_t = typename std::remove_all_extents<T>::type;
00538 
00539 template <size_t Len, size_t Align = type_traits_internal::
00540                           default_alignment_of_aligned_storage<Len>::value>
00541 using aligned_storage_t = typename std::aligned_storage<Len, Align>::type;
00542 
00543 template <typename T>
00544 using decay_t = typename std::decay<T>::type;
00545 
00546 template <bool B, typename T = void>
00547 using enable_if_t = typename std::enable_if<B, T>::type;
00548 
00549 template <bool B, typename T, typename F>
00550 using conditional_t = typename std::conditional<B, T, F>::type;
00551 
00552 template <typename... T>
00553 using common_type_t = typename std::common_type<T...>::type;
00554 
00555 template <typename T>
00556 using underlying_type_t = typename std::underlying_type<T>::type;
00557 
00558 template <typename T>
00559 using result_of_t = typename std::result_of<T>::type;
00560 
00561 namespace type_traits_internal {
00562 // In MSVC we can't probe std::hash or stdext::hash because it triggers a
00563 // static_assert instead of failing substitution. Libc++ prior to 4.0
00564 // also used a static_assert.
00565 //
00566 #if defined(_MSC_VER) || (defined(_LIBCPP_VERSION) && \
00567                           _LIBCPP_VERSION < 4000 && _LIBCPP_STD_VER > 11)
00568 #define ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_ 0
00569 #else
00570 #define ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_ 1
00571 #endif
00572 
00573 #if !ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
00574 template <typename Key, typename = size_t>
00575 struct IsHashable : std::true_type {};
00576 #else   // ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
00577 template <typename Key, typename = void>
00578 struct IsHashable : std::false_type {};
00579 
00580 template <typename Key>
00581 struct IsHashable<
00582     Key,
00583     absl::enable_if_t<std::is_convertible<
00584         decltype(std::declval<std::hash<Key>&>()(std::declval<Key const&>())),
00585         std::size_t>::value>> : std::true_type {};
00586 #endif  // !ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
00587 
00588 struct AssertHashEnabledHelper {
00589  private:
00590   static void Sink(...) {}
00591   struct NAT {};
00592 
00593   template <class Key>
00594   static auto GetReturnType(int)
00595       -> decltype(std::declval<std::hash<Key>>()(std::declval<Key const&>()));
00596   template <class Key>
00597   static NAT GetReturnType(...);
00598 
00599   template <class Key>
00600   static std::nullptr_t DoIt() {
00601     static_assert(IsHashable<Key>::value,
00602                   "std::hash<Key> does not provide a call operator");
00603     static_assert(
00604         std::is_default_constructible<std::hash<Key>>::value,
00605         "std::hash<Key> must be default constructible when it is enabled");
00606     static_assert(
00607         std::is_copy_constructible<std::hash<Key>>::value,
00608         "std::hash<Key> must be copy constructible when it is enabled");
00609     static_assert(absl::is_copy_assignable<std::hash<Key>>::value,
00610                   "std::hash<Key> must be copy assignable when it is enabled");
00611     // is_destructible is unchecked as it's implied by each of the
00612     // is_constructible checks.
00613     using ReturnType = decltype(GetReturnType<Key>(0));
00614     static_assert(std::is_same<ReturnType, NAT>::value ||
00615                       std::is_same<ReturnType, size_t>::value,
00616                   "std::hash<Key> must return size_t");
00617     return nullptr;
00618   }
00619 
00620   template <class... Ts>
00621   friend void AssertHashEnabled();
00622 };
00623 
00624 template <class... Ts>
00625 inline void AssertHashEnabled() {
00626   using Helper = AssertHashEnabledHelper;
00627   Helper::Sink(Helper::DoIt<Ts>()...);
00628 }
00629 
00630 }  // namespace type_traits_internal
00631 
00632 // An internal namespace that is required to implement the C++17 swap traits.
00633 // It is not further nested in type_traits_internal to avoid long symbol names.
00634 namespace swap_internal {
00635 
00636 // Necessary for the traits.
00637 using std::swap;
00638 
00639 // This declaration prevents global `swap` and `absl::swap` overloads from being
00640 // considered unless ADL picks them up.
00641 void swap();
00642 
00643 template <class T>
00644 using IsSwappableImpl = decltype(swap(std::declval<T&>(), std::declval<T&>()));
00645 
00646 // NOTE: This dance with the default template parameter is for MSVC.
00647 template <class T,
00648           class IsNoexcept = std::integral_constant<
00649               bool, noexcept(swap(std::declval<T&>(), std::declval<T&>()))>>
00650 using IsNothrowSwappableImpl = typename std::enable_if<IsNoexcept::value>::type;
00651 
00652 // IsSwappable
00653 //
00654 // Determines whether the standard swap idiom is a valid expression for
00655 // arguments of type `T`.
00656 template <class T>
00657 struct IsSwappable
00658     : absl::type_traits_internal::is_detected<IsSwappableImpl, T> {};
00659 
00660 // IsNothrowSwappable
00661 //
00662 // Determines whether the standard swap idiom is a valid expression for
00663 // arguments of type `T` and is noexcept.
00664 template <class T>
00665 struct IsNothrowSwappable
00666     : absl::type_traits_internal::is_detected<IsNothrowSwappableImpl, T> {};
00667 
00668 // Swap()
00669 //
00670 // Performs the swap idiom from a namespace where valid candidates may only be
00671 // found in `std` or via ADL.
00672 template <class T, absl::enable_if_t<IsSwappable<T>::value, int> = 0>
00673 void Swap(T& lhs, T& rhs) noexcept(IsNothrowSwappable<T>::value) {
00674   swap(lhs, rhs);
00675 }
00676 
00677 // StdSwapIsUnconstrained
00678 //
00679 // Some standard library implementations are broken in that they do not
00680 // constrain `std::swap`. This will effectively tell us if we are dealing with
00681 // one of those implementations.
00682 using StdSwapIsUnconstrained = IsSwappable<void()>;
00683 
00684 }  // namespace swap_internal
00685 
00686 namespace type_traits_internal {
00687 
00688 // Make the swap-related traits/function accessible from this namespace.
00689 using swap_internal::IsNothrowSwappable;
00690 using swap_internal::IsSwappable;
00691 using swap_internal::Swap;
00692 using swap_internal::StdSwapIsUnconstrained;
00693 
00694 }  // namespace type_traits_internal
00695 }  // namespace absl
00696 
00697 #endif  // ABSL_META_TYPE_TRAITS_H_


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