Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2024-11-15 09:01:06

0001 //
0002 // Copyright 2017 The Abseil Authors.
0003 //
0004 // Licensed under the Apache License, Version 2.0 (the "License");
0005 // you may not use this file except in compliance with the License.
0006 // You may obtain a copy of the License at
0007 //
0008 //      https://www.apache.org/licenses/LICENSE-2.0
0009 //
0010 // Unless required by applicable law or agreed to in writing, software
0011 // distributed under the License is distributed on an "AS IS" BASIS,
0012 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0013 // See the License for the specific language governing permissions and
0014 // limitations under the License.
0015 //
0016 // -----------------------------------------------------------------------------
0017 // type_traits.h
0018 // -----------------------------------------------------------------------------
0019 //
0020 // This file contains C++11-compatible versions of standard <type_traits> API
0021 // functions for determining the characteristics of types. Such traits can
0022 // support type inference, classification, and transformation, as well as
0023 // make it easier to write templates based on generic type behavior.
0024 //
0025 // See https://en.cppreference.com/w/cpp/header/type_traits
0026 //
0027 // WARNING: use of many of the constructs in this header will count as "complex
0028 // template metaprogramming", so before proceeding, please carefully consider
0029 // https://google.github.io/styleguide/cppguide.html#Template_metaprogramming
0030 //
0031 // WARNING: using template metaprogramming to detect or depend on API
0032 // features is brittle and not guaranteed. Neither the standard library nor
0033 // Abseil provides any guarantee that APIs are stable in the face of template
0034 // metaprogramming. Use with caution.
0035 #ifndef ABSL_META_TYPE_TRAITS_H_
0036 #define ABSL_META_TYPE_TRAITS_H_
0037 
0038 #include <cstddef>
0039 #include <functional>
0040 #include <type_traits>
0041 
0042 #include "absl/base/attributes.h"
0043 #include "absl/base/config.h"
0044 
0045 // Defines the default alignment. `__STDCPP_DEFAULT_NEW_ALIGNMENT__` is a C++17
0046 // feature.
0047 #if defined(__STDCPP_DEFAULT_NEW_ALIGNMENT__)
0048 #define ABSL_INTERNAL_DEFAULT_NEW_ALIGNMENT __STDCPP_DEFAULT_NEW_ALIGNMENT__
0049 #else  // defined(__STDCPP_DEFAULT_NEW_ALIGNMENT__)
0050 #define ABSL_INTERNAL_DEFAULT_NEW_ALIGNMENT alignof(std::max_align_t)
0051 #endif  // defined(__STDCPP_DEFAULT_NEW_ALIGNMENT__)
0052 
0053 namespace absl {
0054 ABSL_NAMESPACE_BEGIN
0055 
0056 namespace type_traits_internal {
0057 
0058 template <typename... Ts>
0059 struct VoidTImpl {
0060   using type = void;
0061 };
0062 
0063 ////////////////////////////////
0064 // Library Fundamentals V2 TS //
0065 ////////////////////////////////
0066 
0067 // NOTE: The `is_detected` family of templates here differ from the library
0068 // fundamentals specification in that for library fundamentals, `Op<Args...>` is
0069 // evaluated as soon as the type `is_detected<Op, Args...>` undergoes
0070 // substitution, regardless of whether or not the `::value` is accessed. That
0071 // is inconsistent with all other standard traits and prevents lazy evaluation
0072 // in larger contexts (such as if the `is_detected` check is a trailing argument
0073 // of a `conjunction`. This implementation opts to instead be lazy in the same
0074 // way that the standard traits are (this "defect" of the detection idiom
0075 // specifications has been reported).
0076 
0077 template <class Enabler, template <class...> class Op, class... Args>
0078 struct is_detected_impl {
0079   using type = std::false_type;
0080 };
0081 
0082 template <template <class...> class Op, class... Args>
0083 struct is_detected_impl<typename VoidTImpl<Op<Args...>>::type, Op, Args...> {
0084   using type = std::true_type;
0085 };
0086 
0087 template <template <class...> class Op, class... Args>
0088 struct is_detected : is_detected_impl<void, Op, Args...>::type {};
0089 
0090 template <class Enabler, class To, template <class...> class Op, class... Args>
0091 struct is_detected_convertible_impl {
0092   using type = std::false_type;
0093 };
0094 
0095 template <class To, template <class...> class Op, class... Args>
0096 struct is_detected_convertible_impl<
0097     typename std::enable_if<std::is_convertible<Op<Args...>, To>::value>::type,
0098     To, Op, Args...> {
0099   using type = std::true_type;
0100 };
0101 
0102 template <class To, template <class...> class Op, class... Args>
0103 struct is_detected_convertible
0104     : is_detected_convertible_impl<void, To, Op, Args...>::type {};
0105 
0106 }  // namespace type_traits_internal
0107 
0108 // void_t()
0109 //
0110 // Ignores the type of any its arguments and returns `void`. In general, this
0111 // metafunction allows you to create a general case that maps to `void` while
0112 // allowing specializations that map to specific types.
0113 //
0114 // This metafunction is designed to be a drop-in replacement for the C++17
0115 // `std::void_t` metafunction.
0116 //
0117 // NOTE: `absl::void_t` does not use the standard-specified implementation so
0118 // that it can remain compatible with gcc < 5.1. This can introduce slightly
0119 // different behavior, such as when ordering partial specializations.
0120 template <typename... Ts>
0121 using void_t = typename type_traits_internal::VoidTImpl<Ts...>::type;
0122 
0123 // conjunction
0124 //
0125 // Performs a compile-time logical AND operation on the passed types (which
0126 // must have  `::value` members convertible to `bool`. Short-circuits if it
0127 // encounters any `false` members (and does not compare the `::value` members
0128 // of any remaining arguments).
0129 //
0130 // This metafunction is designed to be a drop-in replacement for the C++17
0131 // `std::conjunction` metafunction.
0132 template <typename... Ts>
0133 struct conjunction : std::true_type {};
0134 
0135 template <typename T, typename... Ts>
0136 struct conjunction<T, Ts...>
0137     : std::conditional<T::value, conjunction<Ts...>, T>::type {};
0138 
0139 template <typename T>
0140 struct conjunction<T> : T {};
0141 
0142 // disjunction
0143 //
0144 // Performs a compile-time logical OR operation on the passed types (which
0145 // must have  `::value` members convertible to `bool`. Short-circuits if it
0146 // encounters any `true` members (and does not compare the `::value` members
0147 // of any remaining arguments).
0148 //
0149 // This metafunction is designed to be a drop-in replacement for the C++17
0150 // `std::disjunction` metafunction.
0151 template <typename... Ts>
0152 struct disjunction : std::false_type {};
0153 
0154 template <typename T, typename... Ts>
0155 struct disjunction<T, Ts...> :
0156       std::conditional<T::value, T, disjunction<Ts...>>::type {};
0157 
0158 template <typename T>
0159 struct disjunction<T> : T {};
0160 
0161 // negation
0162 //
0163 // Performs a compile-time logical NOT operation on the passed type (which
0164 // must have  `::value` members convertible to `bool`.
0165 //
0166 // This metafunction is designed to be a drop-in replacement for the C++17
0167 // `std::negation` metafunction.
0168 template <typename T>
0169 struct negation : std::integral_constant<bool, !T::value> {};
0170 
0171 // is_function()
0172 //
0173 // Determines whether the passed type `T` is a function type.
0174 //
0175 // This metafunction is designed to be a drop-in replacement for the C++11
0176 // `std::is_function()` metafunction for platforms that have incomplete C++11
0177 // support (such as libstdc++ 4.x).
0178 //
0179 // This metafunction works because appending `const` to a type does nothing to
0180 // function types and reference types (and forms a const-qualified type
0181 // otherwise).
0182 template <typename T>
0183 struct is_function
0184     : std::integral_constant<
0185           bool, !(std::is_reference<T>::value ||
0186                   std::is_const<typename std::add_const<T>::type>::value)> {};
0187 
0188 // is_copy_assignable()
0189 // is_move_assignable()
0190 // is_trivially_destructible()
0191 // is_trivially_default_constructible()
0192 // is_trivially_move_constructible()
0193 // is_trivially_copy_constructible()
0194 // is_trivially_move_assignable()
0195 // is_trivially_copy_assignable()
0196 //
0197 // Historical note: Abseil once provided implementations of these type traits
0198 // for platforms that lacked full support. New code should prefer to use the
0199 // std variants.
0200 //
0201 // See the documentation for the STL <type_traits> header for more information:
0202 // https://en.cppreference.com/w/cpp/header/type_traits
0203 using std::is_copy_assignable;
0204 using std::is_move_assignable;
0205 using std::is_trivially_copy_assignable;
0206 using std::is_trivially_copy_constructible;
0207 using std::is_trivially_default_constructible;
0208 using std::is_trivially_destructible;
0209 using std::is_trivially_move_assignable;
0210 using std::is_trivially_move_constructible;
0211 
0212 #if defined(__cpp_lib_remove_cvref) && __cpp_lib_remove_cvref >= 201711L
0213 template <typename T>
0214 using remove_cvref = std::remove_cvref<T>;
0215 
0216 template <typename T>
0217 using remove_cvref_t = typename std::remove_cvref<T>::type;
0218 #else
0219 // remove_cvref()
0220 //
0221 // C++11 compatible implementation of std::remove_cvref which was added in
0222 // C++20.
0223 template <typename T>
0224 struct remove_cvref {
0225   using type =
0226       typename std::remove_cv<typename std::remove_reference<T>::type>::type;
0227 };
0228 
0229 template <typename T>
0230 using remove_cvref_t = typename remove_cvref<T>::type;
0231 #endif
0232 
0233 // -----------------------------------------------------------------------------
0234 // C++14 "_t" trait aliases
0235 // -----------------------------------------------------------------------------
0236 
0237 template <typename T>
0238 using remove_cv_t = typename std::remove_cv<T>::type;
0239 
0240 template <typename T>
0241 using remove_const_t = typename std::remove_const<T>::type;
0242 
0243 template <typename T>
0244 using remove_volatile_t = typename std::remove_volatile<T>::type;
0245 
0246 template <typename T>
0247 using add_cv_t = typename std::add_cv<T>::type;
0248 
0249 template <typename T>
0250 using add_const_t = typename std::add_const<T>::type;
0251 
0252 template <typename T>
0253 using add_volatile_t = typename std::add_volatile<T>::type;
0254 
0255 template <typename T>
0256 using remove_reference_t = typename std::remove_reference<T>::type;
0257 
0258 template <typename T>
0259 using add_lvalue_reference_t = typename std::add_lvalue_reference<T>::type;
0260 
0261 template <typename T>
0262 using add_rvalue_reference_t = typename std::add_rvalue_reference<T>::type;
0263 
0264 template <typename T>
0265 using remove_pointer_t = typename std::remove_pointer<T>::type;
0266 
0267 template <typename T>
0268 using add_pointer_t = typename std::add_pointer<T>::type;
0269 
0270 template <typename T>
0271 using make_signed_t = typename std::make_signed<T>::type;
0272 
0273 template <typename T>
0274 using make_unsigned_t = typename std::make_unsigned<T>::type;
0275 
0276 template <typename T>
0277 using remove_extent_t = typename std::remove_extent<T>::type;
0278 
0279 template <typename T>
0280 using remove_all_extents_t = typename std::remove_all_extents<T>::type;
0281 
0282 ABSL_INTERNAL_DISABLE_DEPRECATED_DECLARATION_WARNING
0283 namespace type_traits_internal {
0284 // This trick to retrieve a default alignment is necessary for our
0285 // implementation of aligned_storage_t to be consistent with any
0286 // implementation of std::aligned_storage.
0287 template <size_t Len, typename T = std::aligned_storage<Len>>
0288 struct default_alignment_of_aligned_storage;
0289 
0290 template <size_t Len, size_t Align>
0291 struct default_alignment_of_aligned_storage<
0292     Len, std::aligned_storage<Len, Align>> {
0293   static constexpr size_t value = Align;
0294 };
0295 }  // namespace type_traits_internal
0296 
0297 // TODO(b/260219225): std::aligned_storage(_t) is deprecated in C++23.
0298 template <size_t Len, size_t Align = type_traits_internal::
0299                           default_alignment_of_aligned_storage<Len>::value>
0300 using aligned_storage_t = typename std::aligned_storage<Len, Align>::type;
0301 ABSL_INTERNAL_RESTORE_DEPRECATED_DECLARATION_WARNING
0302 
0303 template <typename T>
0304 using decay_t = typename std::decay<T>::type;
0305 
0306 template <bool B, typename T = void>
0307 using enable_if_t = typename std::enable_if<B, T>::type;
0308 
0309 template <bool B, typename T, typename F>
0310 using conditional_t = typename std::conditional<B, T, F>::type;
0311 
0312 template <typename... T>
0313 using common_type_t = typename std::common_type<T...>::type;
0314 
0315 template <typename T>
0316 using underlying_type_t = typename std::underlying_type<T>::type;
0317 
0318 
0319 namespace type_traits_internal {
0320 
0321 #if (defined(__cpp_lib_is_invocable) && __cpp_lib_is_invocable >= 201703L) || \
0322     (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
0323 // std::result_of is deprecated (C++17) or removed (C++20)
0324 template<typename> struct result_of;
0325 template<typename F, typename... Args>
0326 struct result_of<F(Args...)> : std::invoke_result<F, Args...> {};
0327 #else
0328 template<typename F> using result_of = std::result_of<F>;
0329 #endif
0330 
0331 }  // namespace type_traits_internal
0332 
0333 template<typename F>
0334 using result_of_t = typename type_traits_internal::result_of<F>::type;
0335 
0336 namespace type_traits_internal {
0337 // In MSVC we can't probe std::hash or stdext::hash because it triggers a
0338 // static_assert instead of failing substitution. Libc++ prior to 4.0
0339 // also used a static_assert.
0340 //
0341 #if defined(_MSC_VER) || (defined(_LIBCPP_VERSION) && \
0342                           _LIBCPP_VERSION < 4000 && _LIBCPP_STD_VER > 11)
0343 #define ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_ 0
0344 #else
0345 #define ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_ 1
0346 #endif
0347 
0348 #if !ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
0349 template <typename Key, typename = size_t>
0350 struct IsHashable : std::true_type {};
0351 #else   // ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
0352 template <typename Key, typename = void>
0353 struct IsHashable : std::false_type {};
0354 
0355 template <typename Key>
0356 struct IsHashable<
0357     Key,
0358     absl::enable_if_t<std::is_convertible<
0359         decltype(std::declval<std::hash<Key>&>()(std::declval<Key const&>())),
0360         std::size_t>::value>> : std::true_type {};
0361 #endif  // !ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
0362 
0363 struct AssertHashEnabledHelper {
0364  private:
0365   static void Sink(...) {}
0366   struct NAT {};
0367 
0368   template <class Key>
0369   static auto GetReturnType(int)
0370       -> decltype(std::declval<std::hash<Key>>()(std::declval<Key const&>()));
0371   template <class Key>
0372   static NAT GetReturnType(...);
0373 
0374   template <class Key>
0375   static std::nullptr_t DoIt() {
0376     static_assert(IsHashable<Key>::value,
0377                   "std::hash<Key> does not provide a call operator");
0378     static_assert(
0379         std::is_default_constructible<std::hash<Key>>::value,
0380         "std::hash<Key> must be default constructible when it is enabled");
0381     static_assert(
0382         std::is_copy_constructible<std::hash<Key>>::value,
0383         "std::hash<Key> must be copy constructible when it is enabled");
0384     static_assert(absl::is_copy_assignable<std::hash<Key>>::value,
0385                   "std::hash<Key> must be copy assignable when it is enabled");
0386     // is_destructible is unchecked as it's implied by each of the
0387     // is_constructible checks.
0388     using ReturnType = decltype(GetReturnType<Key>(0));
0389     static_assert(std::is_same<ReturnType, NAT>::value ||
0390                       std::is_same<ReturnType, size_t>::value,
0391                   "std::hash<Key> must return size_t");
0392     return nullptr;
0393   }
0394 
0395   template <class... Ts>
0396   friend void AssertHashEnabled();
0397 };
0398 
0399 template <class... Ts>
0400 inline void AssertHashEnabled() {
0401   using Helper = AssertHashEnabledHelper;
0402   Helper::Sink(Helper::DoIt<Ts>()...);
0403 }
0404 
0405 }  // namespace type_traits_internal
0406 
0407 // An internal namespace that is required to implement the C++17 swap traits.
0408 // It is not further nested in type_traits_internal to avoid long symbol names.
0409 namespace swap_internal {
0410 
0411 // Necessary for the traits.
0412 using std::swap;
0413 
0414 // This declaration prevents global `swap` and `absl::swap` overloads from being
0415 // considered unless ADL picks them up.
0416 void swap();
0417 
0418 template <class T>
0419 using IsSwappableImpl = decltype(swap(std::declval<T&>(), std::declval<T&>()));
0420 
0421 // NOTE: This dance with the default template parameter is for MSVC.
0422 template <class T,
0423           class IsNoexcept = std::integral_constant<
0424               bool, noexcept(swap(std::declval<T&>(), std::declval<T&>()))>>
0425 using IsNothrowSwappableImpl = typename std::enable_if<IsNoexcept::value>::type;
0426 
0427 // IsSwappable
0428 //
0429 // Determines whether the standard swap idiom is a valid expression for
0430 // arguments of type `T`.
0431 template <class T>
0432 struct IsSwappable
0433     : absl::type_traits_internal::is_detected<IsSwappableImpl, T> {};
0434 
0435 // IsNothrowSwappable
0436 //
0437 // Determines whether the standard swap idiom is a valid expression for
0438 // arguments of type `T` and is noexcept.
0439 template <class T>
0440 struct IsNothrowSwappable
0441     : absl::type_traits_internal::is_detected<IsNothrowSwappableImpl, T> {};
0442 
0443 // Swap()
0444 //
0445 // Performs the swap idiom from a namespace where valid candidates may only be
0446 // found in `std` or via ADL.
0447 template <class T, absl::enable_if_t<IsSwappable<T>::value, int> = 0>
0448 void Swap(T& lhs, T& rhs) noexcept(IsNothrowSwappable<T>::value) {
0449   swap(lhs, rhs);
0450 }
0451 
0452 // StdSwapIsUnconstrained
0453 //
0454 // Some standard library implementations are broken in that they do not
0455 // constrain `std::swap`. This will effectively tell us if we are dealing with
0456 // one of those implementations.
0457 using StdSwapIsUnconstrained = IsSwappable<void()>;
0458 
0459 }  // namespace swap_internal
0460 
0461 namespace type_traits_internal {
0462 
0463 // Make the swap-related traits/function accessible from this namespace.
0464 using swap_internal::IsNothrowSwappable;
0465 using swap_internal::IsSwappable;
0466 using swap_internal::Swap;
0467 using swap_internal::StdSwapIsUnconstrained;
0468 
0469 }  // namespace type_traits_internal
0470 
0471 // absl::is_trivially_relocatable<T>
0472 //
0473 // Detects whether a type is known to be "trivially relocatable" -- meaning it
0474 // can be relocated without invoking the constructor/destructor, using a form of
0475 // move elision.
0476 //
0477 // This trait is conservative, for backwards compatibility. If it's true then
0478 // the type is definitely trivially relocatable, but if it's false then the type
0479 // may or may not be.
0480 //
0481 // Example:
0482 //
0483 // if constexpr (absl::is_trivially_relocatable<T>::value) {
0484 //   memcpy(new_location, old_location, sizeof(T));
0485 // } else {
0486 //   new(new_location) T(std::move(*old_location));
0487 //   old_location->~T();
0488 // }
0489 //
0490 // Upstream documentation:
0491 //
0492 // https://clang.llvm.org/docs/LanguageExtensions.html#:~:text=__is_trivially_relocatable
0493 
0494 // If the compiler offers a builtin that tells us the answer, we can use that.
0495 // This covers all of the cases in the fallback below, plus types that opt in
0496 // using e.g. [[clang::trivial_abi]].
0497 //
0498 // Clang on Windows has the builtin, but it falsely claims types with a
0499 // user-provided destructor are trivial (http://b/275003464). So we opt out
0500 // there.
0501 //
0502 // TODO(b/275003464): remove the opt-out once the bug is fixed.
0503 //
0504 // According to https://github.com/abseil/abseil-cpp/issues/1479, this does not
0505 // work with NVCC either.
0506 #if ABSL_HAVE_BUILTIN(__is_trivially_relocatable) &&                 \
0507     !(defined(__clang__) && (defined(_WIN32) || defined(_WIN64))) && \
0508     !defined(__NVCC__)
0509 template <class T>
0510 struct is_trivially_relocatable
0511     : std::integral_constant<bool, __is_trivially_relocatable(T)> {};
0512 #else
0513 // Otherwise we use a fallback that detects only those types we can feasibly
0514 // detect. Any time that has trivial move-construction and destruction
0515 // operations is by definition trivially relocatable.
0516 template <class T>
0517 struct is_trivially_relocatable
0518     : absl::conjunction<absl::is_trivially_move_constructible<T>,
0519                         absl::is_trivially_destructible<T>> {};
0520 #endif
0521 
0522 // absl::is_constant_evaluated()
0523 //
0524 // Detects whether the function call occurs within a constant-evaluated context.
0525 // Returns true if the evaluation of the call occurs within the evaluation of an
0526 // expression or conversion that is manifestly constant-evaluated; otherwise
0527 // returns false.
0528 //
0529 // This function is implemented in terms of `std::is_constant_evaluated` for
0530 // c++20 and up. For older c++ versions, the function is implemented in terms
0531 // of `__builtin_is_constant_evaluated` if available, otherwise the function
0532 // will fail to compile.
0533 //
0534 // Applications can inspect `ABSL_HAVE_CONSTANT_EVALUATED` at compile time
0535 // to check if this function is supported.
0536 //
0537 // Example:
0538 //
0539 // constexpr MyClass::MyClass(int param) {
0540 // #ifdef ABSL_HAVE_CONSTANT_EVALUATED
0541 //   if (!absl::is_constant_evaluated()) {
0542 //     ABSL_LOG(INFO) << "MyClass(" << param << ")";
0543 //   }
0544 // #endif  // ABSL_HAVE_CONSTANT_EVALUATED
0545 // }
0546 //
0547 // Upstream documentation:
0548 //
0549 // http://en.cppreference.com/w/cpp/types/is_constant_evaluated
0550 // http://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html#:~:text=__builtin_is_constant_evaluated
0551 //
0552 #if defined(ABSL_HAVE_CONSTANT_EVALUATED)
0553 constexpr bool is_constant_evaluated() noexcept {
0554 #ifdef __cpp_lib_is_constant_evaluated
0555   return std::is_constant_evaluated();
0556 #elif ABSL_HAVE_BUILTIN(__builtin_is_constant_evaluated)
0557   return __builtin_is_constant_evaluated();
0558 #endif
0559 }
0560 #endif  // ABSL_HAVE_CONSTANT_EVALUATED
0561 ABSL_NAMESPACE_END
0562 }  // namespace absl
0563 
0564 #endif  // ABSL_META_TYPE_TRAITS_H_