// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef BASE_TEMPLATE_UTIL_H_ #define BASE_TEMPLATE_UTIL_H_ #include #include #include #include #include #include "base/compiler_specific.h" namespace base { namespace internal { // Uses expression SFINAE to detect whether using operator<< would work. template struct SupportsOstreamOperator : std::false_type {}; template struct SupportsOstreamOperator() << std::declval()))> : std::true_type {}; template struct SupportsToString : std::false_type {}; template struct SupportsToString().ToString()))> : std::true_type {}; // Used to detech whether the given type is an iterator. This is normally used // with std::enable_if to provide disambiguation for functions that take // templatzed iterators as input. template struct is_iterator : std::false_type {}; template struct is_iterator< T, std::void_t::iterator_category>> : std::true_type {}; // Helper to express preferences in an overload set. If more than one overload // are available for a given set of parameters the overload with the higher // priority will be chosen. template struct priority_tag : priority_tag {}; template <> struct priority_tag<0> {}; } // namespace internal namespace internal { // The indirection with std::is_enum is required, because instantiating // std::underlying_type_t when T is not an enum is UB prior to C++20. template ::value> struct IsScopedEnumImpl : std::false_type {}; template struct IsScopedEnumImpl::value=*/true> : std::negation>> {}; } // namespace internal // Implementation of C++23's std::is_scoped_enum // // Reference: https://en.cppreference.com/w/cpp/types/is_scoped_enum template struct is_scoped_enum : internal::IsScopedEnumImpl {}; // Implementation of C++20's std::remove_cvref. // // References: // - https://en.cppreference.com/w/cpp/types/remove_cvref // - https://wg21.link/meta.trans.other#lib:remove_cvref template struct remove_cvref { using type = std::remove_cv_t>; }; // Implementation of C++20's std::remove_cvref_t. // // References: // - https://en.cppreference.com/w/cpp/types/remove_cvref // - https://wg21.link/meta.type.synop#lib:remove_cvref_t template using remove_cvref_t = typename remove_cvref::type; // Implementation of C++20's std::is_constant_evaluated. // // References: // - https://en.cppreference.com/w/cpp/types/is_constant_evaluated // - https://wg21.link/meta.const.eval constexpr bool is_constant_evaluated() noexcept { #if HAS_BUILTIN(__builtin_is_constant_evaluated) return __builtin_is_constant_evaluated(); #else return false; #endif } // Simplified implementation of C++20's std::iter_value_t. // As opposed to std::iter_value_t, this implementation does not restrict // the type of `Iter` and does not consider specializations of // `indirectly_readable_traits`. // // Reference: https://wg21.link/readable.traits#2 template struct IterValueImpl { using value_type = typename std::iterator_traits::value_type; }; template struct IterValuePointerImpl { // The `iterator_traits::value_type` member is not defined if T is not an // object in C++20. }; template struct IterValuePointerImpl { using value_type = typename std::iterator_traits::value_type; }; template struct IterValueImpl { using value_type = typename IterValuePointerImpl>::value_type; }; template using iter_value_t = typename IterValueImpl>::value_type; // Simplified implementation of C++20's std::iter_reference_t. // As opposed to std::iter_reference_t, this implementation does not restrict // the type of `Iter`. // // Reference: https://wg21.link/iterator.synopsis#:~:text=iter_reference_t template using iter_reference_t = decltype(*std::declval()); // Simplified implementation of C++20's std::indirect_result_t. As opposed to // std::indirect_result_t, this implementation does not restrict the type of // `Func` and `Iters`. // // Reference: https://wg21.link/iterator.synopsis#:~:text=indirect_result_t template using indirect_result_t = std::invoke_result_t...>; // Simplified implementation of C++20's std::projected. As opposed to // std::projected, this implementation does not explicitly restrict the type of // `Iter` and `Proj`, but rather does so implicitly by requiring // `indirect_result_t` is a valid type. This is required for SFINAE // friendliness. // // Reference: https://wg21.link/projected template > struct projected { using value_type = remove_cvref_t; IndirectResultT operator*() const; // not defined }; } // namespace base #endif // BASE_TEMPLATE_UTIL_H_