template_util.h 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. // Copyright (c) 2011 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #ifndef BASE_TEMPLATE_UTIL_H_
  5. #define BASE_TEMPLATE_UTIL_H_
  6. #include <stddef.h>
  7. #include <iosfwd>
  8. #include <iterator>
  9. #include <type_traits>
  10. #include <utility>
  11. #include "base/compiler_specific.h"
  12. namespace base {
  13. namespace internal {
  14. // Uses expression SFINAE to detect whether using operator<< would work.
  15. template <typename T, typename = void>
  16. struct SupportsOstreamOperator : std::false_type {};
  17. template <typename T>
  18. struct SupportsOstreamOperator<T,
  19. decltype(void(std::declval<std::ostream&>()
  20. << std::declval<T>()))>
  21. : std::true_type {};
  22. template <typename T, typename = void>
  23. struct SupportsToString : std::false_type {};
  24. template <typename T>
  25. struct SupportsToString<T, decltype(void(std::declval<T>().ToString()))>
  26. : std::true_type {};
  27. // Used to detech whether the given type is an iterator. This is normally used
  28. // with std::enable_if to provide disambiguation for functions that take
  29. // templatzed iterators as input.
  30. template <typename T, typename = void>
  31. struct is_iterator : std::false_type {};
  32. template <typename T>
  33. struct is_iterator<
  34. T,
  35. std::void_t<typename std::iterator_traits<T>::iterator_category>>
  36. : std::true_type {};
  37. // Helper to express preferences in an overload set. If more than one overload
  38. // are available for a given set of parameters the overload with the higher
  39. // priority will be chosen.
  40. template <size_t I>
  41. struct priority_tag : priority_tag<I - 1> {};
  42. template <>
  43. struct priority_tag<0> {};
  44. } // namespace internal
  45. namespace internal {
  46. // The indirection with std::is_enum<T> is required, because instantiating
  47. // std::underlying_type_t<T> when T is not an enum is UB prior to C++20.
  48. template <typename T, bool = std::is_enum<T>::value>
  49. struct IsScopedEnumImpl : std::false_type {};
  50. template <typename T>
  51. struct IsScopedEnumImpl<T, /*std::is_enum<T>::value=*/true>
  52. : std::negation<std::is_convertible<T, std::underlying_type_t<T>>> {};
  53. } // namespace internal
  54. // Implementation of C++23's std::is_scoped_enum
  55. //
  56. // Reference: https://en.cppreference.com/w/cpp/types/is_scoped_enum
  57. template <typename T>
  58. struct is_scoped_enum : internal::IsScopedEnumImpl<T> {};
  59. // Implementation of C++20's std::remove_cvref.
  60. //
  61. // References:
  62. // - https://en.cppreference.com/w/cpp/types/remove_cvref
  63. // - https://wg21.link/meta.trans.other#lib:remove_cvref
  64. template <typename T>
  65. struct remove_cvref {
  66. using type = std::remove_cv_t<std::remove_reference_t<T>>;
  67. };
  68. // Implementation of C++20's std::remove_cvref_t.
  69. //
  70. // References:
  71. // - https://en.cppreference.com/w/cpp/types/remove_cvref
  72. // - https://wg21.link/meta.type.synop#lib:remove_cvref_t
  73. template <typename T>
  74. using remove_cvref_t = typename remove_cvref<T>::type;
  75. // Implementation of C++20's std::is_constant_evaluated.
  76. //
  77. // References:
  78. // - https://en.cppreference.com/w/cpp/types/is_constant_evaluated
  79. // - https://wg21.link/meta.const.eval
  80. constexpr bool is_constant_evaluated() noexcept {
  81. #if HAS_BUILTIN(__builtin_is_constant_evaluated)
  82. return __builtin_is_constant_evaluated();
  83. #else
  84. return false;
  85. #endif
  86. }
  87. // Simplified implementation of C++20's std::iter_value_t.
  88. // As opposed to std::iter_value_t, this implementation does not restrict
  89. // the type of `Iter` and does not consider specializations of
  90. // `indirectly_readable_traits`.
  91. //
  92. // Reference: https://wg21.link/readable.traits#2
  93. template <typename Iter>
  94. struct IterValueImpl {
  95. using value_type = typename std::iterator_traits<Iter>::value_type;
  96. };
  97. template <typename T, bool Cond = false>
  98. struct IterValuePointerImpl {
  99. // The `iterator_traits<T*>::value_type` member is not defined if T is not an
  100. // object in C++20.
  101. };
  102. template <typename T>
  103. struct IterValuePointerImpl<T*, true> {
  104. using value_type = typename std::iterator_traits<T*>::value_type;
  105. };
  106. template <typename T>
  107. struct IterValueImpl<T*> {
  108. using value_type =
  109. typename IterValuePointerImpl<T*, std::is_object_v<T>>::value_type;
  110. };
  111. template <typename Iter>
  112. using iter_value_t = typename IterValueImpl<remove_cvref_t<Iter>>::value_type;
  113. // Simplified implementation of C++20's std::iter_reference_t.
  114. // As opposed to std::iter_reference_t, this implementation does not restrict
  115. // the type of `Iter`.
  116. //
  117. // Reference: https://wg21.link/iterator.synopsis#:~:text=iter_reference_t
  118. template <typename Iter>
  119. using iter_reference_t = decltype(*std::declval<Iter&>());
  120. // Simplified implementation of C++20's std::indirect_result_t. As opposed to
  121. // std::indirect_result_t, this implementation does not restrict the type of
  122. // `Func` and `Iters`.
  123. //
  124. // Reference: https://wg21.link/iterator.synopsis#:~:text=indirect_result_t
  125. template <typename Func, typename... Iters>
  126. using indirect_result_t =
  127. std::invoke_result_t<Func, iter_reference_t<Iters>...>;
  128. // Simplified implementation of C++20's std::projected. As opposed to
  129. // std::projected, this implementation does not explicitly restrict the type of
  130. // `Iter` and `Proj`, but rather does so implicitly by requiring
  131. // `indirect_result_t<Proj, Iter>` is a valid type. This is required for SFINAE
  132. // friendliness.
  133. //
  134. // Reference: https://wg21.link/projected
  135. template <typename Iter,
  136. typename Proj,
  137. typename IndirectResultT = indirect_result_t<Proj, Iter>>
  138. struct projected {
  139. using value_type = remove_cvref_t<IndirectResultT>;
  140. IndirectResultT operator*() const; // not defined
  141. };
  142. } // namespace base
  143. #endif // BASE_TEMPLATE_UTIL_H_