Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-02 08:05:13

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 <string>
0041 #include <type_traits>
0042 #include <vector>
0043 
0044 #include "absl/base/attributes.h"
0045 #include "absl/base/config.h"
0046 
0047 #ifdef __cpp_lib_span
0048 #include <span>  // NOLINT(build/c++20)
0049 #endif
0050 
0051 #ifdef ABSL_HAVE_STD_STRING_VIEW
0052 #include <string_view>
0053 #endif
0054 
0055 // Defines the default alignment. `__STDCPP_DEFAULT_NEW_ALIGNMENT__` is a C++17
0056 // feature.
0057 #if defined(__STDCPP_DEFAULT_NEW_ALIGNMENT__)
0058 #define ABSL_INTERNAL_DEFAULT_NEW_ALIGNMENT __STDCPP_DEFAULT_NEW_ALIGNMENT__
0059 #else  // defined(__STDCPP_DEFAULT_NEW_ALIGNMENT__)
0060 #define ABSL_INTERNAL_DEFAULT_NEW_ALIGNMENT alignof(std::max_align_t)
0061 #endif  // defined(__STDCPP_DEFAULT_NEW_ALIGNMENT__)
0062 
0063 namespace absl {
0064 ABSL_NAMESPACE_BEGIN
0065 
0066 namespace type_traits_internal {
0067 
0068 template <typename... Ts>
0069 struct VoidTImpl {
0070   using type = void;
0071 };
0072 
0073 ////////////////////////////////
0074 // Library Fundamentals V2 TS //
0075 ////////////////////////////////
0076 
0077 // NOTE: The `is_detected` family of templates here differ from the library
0078 // fundamentals specification in that for library fundamentals, `Op<Args...>` is
0079 // evaluated as soon as the type `is_detected<Op, Args...>` undergoes
0080 // substitution, regardless of whether or not the `::value` is accessed. That
0081 // is inconsistent with all other standard traits and prevents lazy evaluation
0082 // in larger contexts (such as if the `is_detected` check is a trailing argument
0083 // of a `conjunction`. This implementation opts to instead be lazy in the same
0084 // way that the standard traits are (this "defect" of the detection idiom
0085 // specifications has been reported).
0086 
0087 template <class Enabler, template <class...> class Op, class... Args>
0088 struct is_detected_impl {
0089   using type = std::false_type;
0090 };
0091 
0092 template <template <class...> class Op, class... Args>
0093 struct is_detected_impl<typename VoidTImpl<Op<Args...>>::type, Op, Args...> {
0094   using type = std::true_type;
0095 };
0096 
0097 template <template <class...> class Op, class... Args>
0098 struct is_detected : is_detected_impl<void, Op, Args...>::type {};
0099 
0100 template <class Enabler, class To, template <class...> class Op, class... Args>
0101 struct is_detected_convertible_impl {
0102   using type = std::false_type;
0103 };
0104 
0105 template <class To, template <class...> class Op, class... Args>
0106 struct is_detected_convertible_impl<
0107     typename std::enable_if<std::is_convertible<Op<Args...>, To>::value>::type,
0108     To, Op, Args...> {
0109   using type = std::true_type;
0110 };
0111 
0112 template <class To, template <class...> class Op, class... Args>
0113 struct is_detected_convertible
0114     : is_detected_convertible_impl<void, To, Op, Args...>::type {};
0115 
0116 }  // namespace type_traits_internal
0117 
0118 // void_t()
0119 //
0120 // Ignores the type of any its arguments and returns `void`. In general, this
0121 // metafunction allows you to create a general case that maps to `void` while
0122 // allowing specializations that map to specific types.
0123 //
0124 // This metafunction is designed to be a drop-in replacement for the C++17
0125 // `std::void_t` metafunction.
0126 //
0127 // NOTE: `absl::void_t` does not use the standard-specified implementation so
0128 // that it can remain compatible with gcc < 5.1. This can introduce slightly
0129 // different behavior, such as when ordering partial specializations.
0130 template <typename... Ts>
0131 using void_t = typename type_traits_internal::VoidTImpl<Ts...>::type;
0132 
0133 // conjunction
0134 //
0135 // Performs a compile-time logical AND operation on the passed types (which
0136 // must have  `::value` members convertible to `bool`. Short-circuits if it
0137 // encounters any `false` members (and does not compare the `::value` members
0138 // of any remaining arguments).
0139 //
0140 // This metafunction is designed to be a drop-in replacement for the C++17
0141 // `std::conjunction` metafunction.
0142 template <typename... Ts>
0143 struct conjunction : std::true_type {};
0144 
0145 template <typename T, typename... Ts>
0146 struct conjunction<T, Ts...>
0147     : std::conditional<T::value, conjunction<Ts...>, T>::type {};
0148 
0149 template <typename T>
0150 struct conjunction<T> : T {};
0151 
0152 // disjunction
0153 //
0154 // Performs a compile-time logical OR operation on the passed types (which
0155 // must have  `::value` members convertible to `bool`. Short-circuits if it
0156 // encounters any `true` members (and does not compare the `::value` members
0157 // of any remaining arguments).
0158 //
0159 // This metafunction is designed to be a drop-in replacement for the C++17
0160 // `std::disjunction` metafunction.
0161 template <typename... Ts>
0162 struct disjunction : std::false_type {};
0163 
0164 template <typename T, typename... Ts>
0165 struct disjunction<T, Ts...>
0166     : std::conditional<T::value, T, disjunction<Ts...>>::type {};
0167 
0168 template <typename T>
0169 struct disjunction<T> : T {};
0170 
0171 // negation
0172 //
0173 // Performs a compile-time logical NOT operation on the passed type (which
0174 // must have  `::value` members convertible to `bool`.
0175 //
0176 // This metafunction is designed to be a drop-in replacement for the C++17
0177 // `std::negation` metafunction.
0178 template <typename T>
0179 struct negation : std::integral_constant<bool, !T::value> {};
0180 
0181 // is_function()
0182 //
0183 // Determines whether the passed type `T` is a function type.
0184 //
0185 // This metafunction is designed to be a drop-in replacement for the C++11
0186 // `std::is_function()` metafunction for platforms that have incomplete C++11
0187 // support (such as libstdc++ 4.x).
0188 //
0189 // This metafunction works because appending `const` to a type does nothing to
0190 // function types and reference types (and forms a const-qualified type
0191 // otherwise).
0192 template <typename T>
0193 struct is_function
0194     : std::integral_constant<
0195           bool, !(std::is_reference<T>::value ||
0196                   std::is_const<typename std::add_const<T>::type>::value)> {};
0197 
0198 // is_copy_assignable()
0199 // is_move_assignable()
0200 // is_trivially_destructible()
0201 // is_trivially_default_constructible()
0202 // is_trivially_move_constructible()
0203 // is_trivially_copy_constructible()
0204 // is_trivially_move_assignable()
0205 // is_trivially_copy_assignable()
0206 //
0207 // Historical note: Abseil once provided implementations of these type traits
0208 // for platforms that lacked full support. New code should prefer to use the
0209 // std variants.
0210 //
0211 // See the documentation for the STL <type_traits> header for more information:
0212 // https://en.cppreference.com/w/cpp/header/type_traits
0213 using std::is_copy_assignable;
0214 using std::is_move_assignable;
0215 using std::is_trivially_copy_assignable;
0216 using std::is_trivially_copy_constructible;
0217 using std::is_trivially_default_constructible;
0218 using std::is_trivially_destructible;
0219 using std::is_trivially_move_assignable;
0220 using std::is_trivially_move_constructible;
0221 
0222 #if defined(__cpp_lib_remove_cvref) && __cpp_lib_remove_cvref >= 201711L
0223 template <typename T>
0224 using remove_cvref = std::remove_cvref<T>;
0225 
0226 template <typename T>
0227 using remove_cvref_t = typename std::remove_cvref<T>::type;
0228 #else
0229 // remove_cvref()
0230 //
0231 // C++11 compatible implementation of std::remove_cvref which was added in
0232 // C++20.
0233 template <typename T>
0234 struct remove_cvref {
0235   using type =
0236       typename std::remove_cv<typename std::remove_reference<T>::type>::type;
0237 };
0238 
0239 template <typename T>
0240 using remove_cvref_t = typename remove_cvref<T>::type;
0241 #endif
0242 
0243 // -----------------------------------------------------------------------------
0244 // C++14 "_t" trait aliases
0245 // -----------------------------------------------------------------------------
0246 
0247 template <typename T>
0248 using remove_cv_t = typename std::remove_cv<T>::type;
0249 
0250 template <typename T>
0251 using remove_const_t = typename std::remove_const<T>::type;
0252 
0253 template <typename T>
0254 using remove_volatile_t = typename std::remove_volatile<T>::type;
0255 
0256 template <typename T>
0257 using add_cv_t = typename std::add_cv<T>::type;
0258 
0259 template <typename T>
0260 using add_const_t = typename std::add_const<T>::type;
0261 
0262 template <typename T>
0263 using add_volatile_t = typename std::add_volatile<T>::type;
0264 
0265 template <typename T>
0266 using remove_reference_t = typename std::remove_reference<T>::type;
0267 
0268 template <typename T>
0269 using add_lvalue_reference_t = typename std::add_lvalue_reference<T>::type;
0270 
0271 template <typename T>
0272 using add_rvalue_reference_t = typename std::add_rvalue_reference<T>::type;
0273 
0274 template <typename T>
0275 using remove_pointer_t = typename std::remove_pointer<T>::type;
0276 
0277 template <typename T>
0278 using add_pointer_t = typename std::add_pointer<T>::type;
0279 
0280 template <typename T>
0281 using make_signed_t = typename std::make_signed<T>::type;
0282 
0283 template <typename T>
0284 using make_unsigned_t = typename std::make_unsigned<T>::type;
0285 
0286 template <typename T>
0287 using remove_extent_t = typename std::remove_extent<T>::type;
0288 
0289 template <typename T>
0290 using remove_all_extents_t = typename std::remove_all_extents<T>::type;
0291 
0292 template <typename T>
0293 using decay_t = typename std::decay<T>::type;
0294 
0295 template <bool B, typename T = void>
0296 using enable_if_t = typename std::enable_if<B, T>::type;
0297 
0298 template <bool B, typename T, typename F>
0299 using conditional_t = typename std::conditional<B, T, F>::type;
0300 
0301 template <typename... T>
0302 using common_type_t = typename std::common_type<T...>::type;
0303 
0304 template <typename T>
0305 using underlying_type_t = typename std::underlying_type<T>::type;
0306 
0307 namespace type_traits_internal {
0308 
0309 #if (defined(__cpp_lib_is_invocable) && __cpp_lib_is_invocable >= 201703L) || \
0310     (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
0311 // std::result_of is deprecated (C++17) or removed (C++20)
0312 template <typename>
0313 struct result_of;
0314 template <typename F, typename... Args>
0315 struct result_of<F(Args...)> : std::invoke_result<F, Args...> {};
0316 #else
0317 template <typename F>
0318 using result_of = std::result_of<F>;
0319 #endif
0320 
0321 }  // namespace type_traits_internal
0322 
0323 template <typename F>
0324 using result_of_t = typename type_traits_internal::result_of<F>::type;
0325 
0326 namespace type_traits_internal {
0327 // In MSVC we can't probe std::hash or stdext::hash because it triggers a
0328 // static_assert instead of failing substitution. Libc++ prior to 4.0
0329 // also used a static_assert.
0330 //
0331 #if defined(_MSC_VER) || (defined(_LIBCPP_VERSION) && \
0332                           _LIBCPP_VERSION < 4000 && _LIBCPP_STD_VER > 11)
0333 #define ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_ 0
0334 #else
0335 #define ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_ 1
0336 #endif
0337 
0338 #if !ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
0339 template <typename Key, typename = size_t>
0340 struct IsHashable : std::true_type {};
0341 #else   // ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
0342 template <typename Key, typename = void>
0343 struct IsHashable : std::false_type {};
0344 
0345 template <typename Key>
0346 struct IsHashable<
0347     Key,
0348     absl::enable_if_t<std::is_convertible<
0349         decltype(std::declval<std::hash<Key>&>()(std::declval<Key const&>())),
0350         std::size_t>::value>> : std::true_type {};
0351 #endif  // !ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
0352 
0353 struct AssertHashEnabledHelper {
0354  private:
0355   static void Sink(...) {}
0356   struct NAT {};
0357 
0358   template <class Key>
0359   static auto GetReturnType(int)
0360       -> decltype(std::declval<std::hash<Key>>()(std::declval<Key const&>()));
0361   template <class Key>
0362   static NAT GetReturnType(...);
0363 
0364   template <class Key>
0365   static std::nullptr_t DoIt() {
0366     static_assert(IsHashable<Key>::value,
0367                   "std::hash<Key> does not provide a call operator");
0368     static_assert(
0369         std::is_default_constructible<std::hash<Key>>::value,
0370         "std::hash<Key> must be default constructible when it is enabled");
0371     static_assert(
0372         std::is_copy_constructible<std::hash<Key>>::value,
0373         "std::hash<Key> must be copy constructible when it is enabled");
0374     static_assert(absl::is_copy_assignable<std::hash<Key>>::value,
0375                   "std::hash<Key> must be copy assignable when it is enabled");
0376     // is_destructible is unchecked as it's implied by each of the
0377     // is_constructible checks.
0378     using ReturnType = decltype(GetReturnType<Key>(0));
0379     static_assert(std::is_same<ReturnType, NAT>::value ||
0380                       std::is_same<ReturnType, size_t>::value,
0381                   "std::hash<Key> must return size_t");
0382     return nullptr;
0383   }
0384 
0385   template <class... Ts>
0386   friend void AssertHashEnabled();
0387 };
0388 
0389 template <class... Ts>
0390 inline void AssertHashEnabled() {
0391   using Helper = AssertHashEnabledHelper;
0392   Helper::Sink(Helper::DoIt<Ts>()...);
0393 }
0394 
0395 }  // namespace type_traits_internal
0396 
0397 // An internal namespace that is required to implement the C++17 swap traits.
0398 // It is not further nested in type_traits_internal to avoid long symbol names.
0399 namespace swap_internal {
0400 
0401 // Necessary for the traits.
0402 using std::swap;
0403 
0404 // This declaration prevents global `swap` and `absl::swap` overloads from being
0405 // considered unless ADL picks them up.
0406 void swap();
0407 
0408 template <class T>
0409 using IsSwappableImpl = decltype(swap(std::declval<T&>(), std::declval<T&>()));
0410 
0411 // NOTE: This dance with the default template parameter is for MSVC.
0412 template <class T,
0413           class IsNoexcept = std::integral_constant<
0414               bool, noexcept(swap(std::declval<T&>(), std::declval<T&>()))>>
0415 using IsNothrowSwappableImpl = typename std::enable_if<IsNoexcept::value>::type;
0416 
0417 // IsSwappable
0418 //
0419 // Determines whether the standard swap idiom is a valid expression for
0420 // arguments of type `T`.
0421 template <class T>
0422 struct IsSwappable
0423     : absl::type_traits_internal::is_detected<IsSwappableImpl, T> {};
0424 
0425 // IsNothrowSwappable
0426 //
0427 // Determines whether the standard swap idiom is a valid expression for
0428 // arguments of type `T` and is noexcept.
0429 template <class T>
0430 struct IsNothrowSwappable
0431     : absl::type_traits_internal::is_detected<IsNothrowSwappableImpl, T> {};
0432 
0433 // Swap()
0434 //
0435 // Performs the swap idiom from a namespace where valid candidates may only be
0436 // found in `std` or via ADL.
0437 template <class T, absl::enable_if_t<IsSwappable<T>::value, int> = 0>
0438 void Swap(T& lhs, T& rhs) noexcept(IsNothrowSwappable<T>::value) {
0439   swap(lhs, rhs);
0440 }
0441 
0442 // StdSwapIsUnconstrained
0443 //
0444 // Some standard library implementations are broken in that they do not
0445 // constrain `std::swap`. This will effectively tell us if we are dealing with
0446 // one of those implementations.
0447 using StdSwapIsUnconstrained = IsSwappable<void()>;
0448 
0449 }  // namespace swap_internal
0450 
0451 namespace type_traits_internal {
0452 
0453 // Make the swap-related traits/function accessible from this namespace.
0454 using swap_internal::IsNothrowSwappable;
0455 using swap_internal::IsSwappable;
0456 using swap_internal::StdSwapIsUnconstrained;
0457 using swap_internal::Swap;
0458 
0459 }  // namespace type_traits_internal
0460 
0461 // absl::is_trivially_relocatable<T>
0462 //
0463 // Detects whether a type is known to be "trivially relocatable" -- meaning it
0464 // can be relocated from one place to another as if by memcpy/memmove.
0465 // This implies that its object representation doesn't depend on its address,
0466 // and also none of its special member functions do anything strange.
0467 //
0468 // This trait is conservative. If it's true then the type is definitely
0469 // trivially relocatable, but if it's false then the type may or may not be. For
0470 // example, std::vector<int> is trivially relocatable on every known STL
0471 // implementation, but absl::is_trivially_relocatable<std::vector<int>> remains
0472 // false.
0473 //
0474 // Example:
0475 //
0476 // if constexpr (absl::is_trivially_relocatable<T>::value) {
0477 //   memcpy(new_location, old_location, sizeof(T));
0478 // } else {
0479 //   new(new_location) T(std::move(*old_location));
0480 //   old_location->~T();
0481 // }
0482 //
0483 // Upstream documentation:
0484 //
0485 // https://clang.llvm.org/docs/LanguageExtensions.html#:~:text=__is_trivially_relocatable
0486 
0487 // If the compiler offers a builtin that tells us the answer, we can use that.
0488 // This covers all of the cases in the fallback below, plus types that opt in
0489 // using e.g. [[clang::trivial_abi]].
0490 //
0491 // Clang on Windows has the builtin, but it falsely claims types with a
0492 // user-provided destructor are trivial (http://b/275003464). So we opt out
0493 // there.
0494 //
0495 // TODO(b/275003464): remove the opt-out once the bug is fixed.
0496 //
0497 // Starting with Xcode 15, the Apple compiler will falsely say a type
0498 // with a user-provided move constructor is trivially relocatable
0499 // (b/324278148). We will opt out without a version check, due to
0500 // the fluidity of Apple versions.
0501 //
0502 // TODO(b/324278148): If all versions we use have the bug fixed, then
0503 // remove the condition.
0504 //
0505 // Clang on all platforms fails to detect that a type with a user-provided
0506 // move-assignment operator is not trivially relocatable. So in fact we
0507 // opt out of Clang altogether, for now.
0508 //
0509 // TODO(b/325479096): Remove the opt-out once Clang's behavior is fixed.
0510 //
0511 // According to https://github.com/abseil/abseil-cpp/issues/1479, this does not
0512 // work with NVCC either.
0513 #if ABSL_HAVE_BUILTIN(__is_trivially_relocatable) && \
0514     (defined(__cpp_impl_trivially_relocatable) ||    \
0515      (!defined(__clang__) && !defined(__APPLE__) && !defined(__NVCC__)))
0516 template <class T>
0517 struct is_trivially_relocatable
0518     : std::integral_constant<bool, __is_trivially_relocatable(T)> {};
0519 #else
0520 // Otherwise we use a fallback that detects only those types we can feasibly
0521 // detect. Any type that is trivially copyable is by definition trivially
0522 // relocatable.
0523 template <class T>
0524 struct is_trivially_relocatable : std::is_trivially_copyable<T> {};
0525 #endif
0526 
0527 // absl::is_constant_evaluated()
0528 //
0529 // Detects whether the function call occurs within a constant-evaluated context.
0530 // Returns true if the evaluation of the call occurs within the evaluation of an
0531 // expression or conversion that is manifestly constant-evaluated; otherwise
0532 // returns false.
0533 //
0534 // This function is implemented in terms of `std::is_constant_evaluated` for
0535 // c++20 and up. For older c++ versions, the function is implemented in terms
0536 // of `__builtin_is_constant_evaluated` if available, otherwise the function
0537 // will fail to compile.
0538 //
0539 // Applications can inspect `ABSL_HAVE_CONSTANT_EVALUATED` at compile time
0540 // to check if this function is supported.
0541 //
0542 // Example:
0543 //
0544 // constexpr MyClass::MyClass(int param) {
0545 // #ifdef ABSL_HAVE_CONSTANT_EVALUATED
0546 //   if (!absl::is_constant_evaluated()) {
0547 //     ABSL_LOG(INFO) << "MyClass(" << param << ")";
0548 //   }
0549 // #endif  // ABSL_HAVE_CONSTANT_EVALUATED
0550 // }
0551 //
0552 // Upstream documentation:
0553 //
0554 // http://en.cppreference.com/w/cpp/types/is_constant_evaluated
0555 // http://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html#:~:text=__builtin_is_constant_evaluated
0556 //
0557 #if defined(ABSL_HAVE_CONSTANT_EVALUATED)
0558 constexpr bool is_constant_evaluated() noexcept {
0559 #ifdef __cpp_lib_is_constant_evaluated
0560   return std::is_constant_evaluated();
0561 #elif ABSL_HAVE_BUILTIN(__builtin_is_constant_evaluated)
0562   return __builtin_is_constant_evaluated();
0563 #endif
0564 }
0565 #endif  // ABSL_HAVE_CONSTANT_EVALUATED
0566 
0567 namespace type_traits_internal {
0568 
0569 // Detects if a class's definition has declared itself to be an owner by
0570 // declaring
0571 //   using absl_internal_is_view = std::true_type;
0572 // as a member.
0573 // Types that don't want either must either omit this declaration entirely, or
0574 // (if e.g. inheriting from a base class) define the member to something that
0575 // isn't a Boolean trait class, such as `void`.
0576 // Do not specialize or use this directly. It's an implementation detail.
0577 template <typename T, typename = void>
0578 struct IsOwnerImpl : std::false_type {
0579   static_assert(std::is_same<T, absl::remove_cvref_t<T>>::value,
0580                 "type must lack qualifiers");
0581 };
0582 
0583 template <typename T>
0584 struct IsOwnerImpl<
0585     T,
0586     std::enable_if_t<std::is_class<typename T::absl_internal_is_view>::value>>
0587     : absl::negation<typename T::absl_internal_is_view> {};
0588 
0589 // A trait to determine whether a type is an owner.
0590 // Do *not* depend on the correctness of this trait for correct code behavior.
0591 // It is only a safety feature and its value may change in the future.
0592 // Do not specialize this; instead, define the member trait inside your type so
0593 // that it can be auto-detected, and to prevent ODR violations.
0594 // If it ever becomes possible to detect [[gsl::Owner]], we should leverage it:
0595 // https://wg21.link/p1179
0596 template <typename T>
0597 struct IsOwner : IsOwnerImpl<T> {};
0598 
0599 template <typename T, typename Traits, typename Alloc>
0600 struct IsOwner<std::basic_string<T, Traits, Alloc>> : std::true_type {};
0601 
0602 template <typename T, typename Alloc>
0603 struct IsOwner<std::vector<T, Alloc>> : std::true_type {};
0604 
0605 // Detects if a class's definition has declared itself to be a view by declaring
0606 //   using absl_internal_is_view = std::true_type;
0607 // as a member.
0608 // Do not specialize or use this directly.
0609 template <typename T, typename = void>
0610 struct IsViewImpl : std::false_type {
0611   static_assert(std::is_same<T, absl::remove_cvref_t<T>>::value,
0612                 "type must lack qualifiers");
0613 };
0614 
0615 template <typename T>
0616 struct IsViewImpl<
0617     T,
0618     std::enable_if_t<std::is_class<typename T::absl_internal_is_view>::value>>
0619     : T::absl_internal_is_view {};
0620 
0621 // A trait to determine whether a type is a view.
0622 // Do *not* depend on the correctness of this trait for correct code behavior.
0623 // It is only a safety feature, and its value may change in the future.
0624 // Do not specialize this trait. Instead, define the member
0625 //   using absl_internal_is_view = std::true_type;
0626 // in your class to allow its detection while preventing ODR violations.
0627 // If it ever becomes possible to detect [[gsl::Pointer]], we should leverage
0628 // it: https://wg21.link/p1179
0629 template <typename T>
0630 struct IsView : std::integral_constant<bool, std::is_pointer<T>::value ||
0631                                                  IsViewImpl<T>::value> {};
0632 
0633 #ifdef ABSL_HAVE_STD_STRING_VIEW
0634 template <typename Char, typename Traits>
0635 struct IsView<std::basic_string_view<Char, Traits>> : std::true_type {};
0636 #endif
0637 
0638 #ifdef __cpp_lib_span
0639 template <typename T>
0640 struct IsView<std::span<T>> : std::true_type {};
0641 #endif
0642 
0643 // Determines whether the assignment of the given types is lifetime-bound.
0644 // Do *not* depend on the correctness of this trait for correct code behavior.
0645 // It is only a safety feature and its value may change in the future.
0646 // If it ever becomes possible to detect [[clang::lifetimebound]] directly,
0647 // we should change the implementation to leverage that.
0648 // Until then, we consider an assignment from an "owner" (such as std::string)
0649 // to a "view" (such as std::string_view) to be a lifetime-bound assignment.
0650 template <typename T, typename U>
0651 using IsLifetimeBoundAssignment =
0652     std::integral_constant<bool, IsView<absl::remove_cvref_t<T>>::value &&
0653                                      IsOwner<absl::remove_cvref_t<U>>::value>;
0654 
0655 }  // namespace type_traits_internal
0656 
0657 ABSL_NAMESPACE_END
0658 }  // namespace absl
0659 
0660 #endif  // ABSL_META_TYPE_TRAITS_H_