Avi Drissman | e4622aa | 2022-09-08 20:36:06 | [diff] [blame] | 1 | // Copyright 2011 The Chromium Authors |
willchan@chromium.org | 951269b | 2010-06-15 19:39:24 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #ifndef BASE_TEMPLATE_UTIL_H_ |
| 6 | #define BASE_TEMPLATE_UTIL_H_ |
willchan@chromium.org | 951269b | 2010-06-15 19:39:24 | [diff] [blame] | 7 | |
danakj | a26bdfc | 2016-04-13 22:08:03 | [diff] [blame] | 8 | #include <stddef.h> |
Avi Drissman | 02aadae1 | 2022-05-04 02:50:48 | [diff] [blame] | 9 | |
jbroman | 6bcfec42 | 2016-05-26 00:28:46 | [diff] [blame] | 10 | #include <iosfwd> |
Brett Wilson | 322a546 | 2017-08-03 23:59:12 | [diff] [blame] | 11 | #include <iterator> |
tzik | 403cb6c | 2016-03-10 07:17:25 | [diff] [blame] | 12 | #include <type_traits> |
danakj | a26bdfc | 2016-04-13 22:08:03 | [diff] [blame] | 13 | #include <utility> |
ajwong@chromium.org | b38d357 | 2011-02-15 01:27:38 | [diff] [blame] | 14 | |
Jan Wilken Dörrie | 2d7bca0 | 2021-04-19 19:59:32 | [diff] [blame] | 15 | #include "base/compiler_specific.h" |
willchan@chromium.org | 792cdcf | 2010-12-15 09:55:35 | [diff] [blame] | 16 | |
willchan@chromium.org | 951269b | 2010-06-15 19:39:24 | [diff] [blame] | 17 | namespace base { |
| 18 | |
danakj | a26bdfc | 2016-04-13 22:08:03 | [diff] [blame] | 19 | namespace internal { |
| 20 | |
jbroman | 6bcfec42 | 2016-05-26 00:28:46 | [diff] [blame] | 21 | // Uses expression SFINAE to detect whether using operator<< would work. |
| 22 | template <typename T, typename = void> |
| 23 | struct SupportsOstreamOperator : std::false_type {}; |
| 24 | template <typename T> |
| 25 | struct SupportsOstreamOperator<T, |
| 26 | decltype(void(std::declval<std::ostream&>() |
| 27 | << std::declval<T>()))> |
| 28 | : std::true_type {}; |
| 29 | |
Collin Baker | 89e9e07 | 2019-06-10 22:39:05 | [diff] [blame] | 30 | template <typename T, typename = void> |
| 31 | struct SupportsToString : std::false_type {}; |
| 32 | template <typename T> |
| 33 | struct SupportsToString<T, decltype(void(std::declval<T>().ToString()))> |
| 34 | : std::true_type {}; |
| 35 | |
Brett Wilson | 322a546 | 2017-08-03 23:59:12 | [diff] [blame] | 36 | // Used to detech whether the given type is an iterator. This is normally used |
| 37 | // with std::enable_if to provide disambiguation for functions that take |
| 38 | // templatzed iterators as input. |
| 39 | template <typename T, typename = void> |
| 40 | struct is_iterator : std::false_type {}; |
| 41 | |
| 42 | template <typename T> |
Avi Drissman | 1089236e | 2022-04-28 13:44:41 | [diff] [blame] | 43 | struct is_iterator< |
| 44 | T, |
| 45 | std::void_t<typename std::iterator_traits<T>::iterator_category>> |
Brett Wilson | 322a546 | 2017-08-03 23:59:12 | [diff] [blame] | 46 | : std::true_type {}; |
| 47 | |
Jan Wilken Dörrie | 9f8955f | 2020-09-16 10:27:18 | [diff] [blame] | 48 | // Helper to express preferences in an overload set. If more than one overload |
| 49 | // are available for a given set of parameters the overload with the higher |
| 50 | // priority will be chosen. |
| 51 | template <size_t I> |
| 52 | struct priority_tag : priority_tag<I - 1> {}; |
| 53 | |
| 54 | template <> |
| 55 | struct priority_tag<0> {}; |
| 56 | |
danakj | a26bdfc | 2016-04-13 22:08:03 | [diff] [blame] | 57 | } // namespace internal |
| 58 | |
Jan Wilken Dörrie | f89fc2ac | 2021-03-05 06:51:22 | [diff] [blame] | 59 | namespace internal { |
| 60 | |
| 61 | // The indirection with std::is_enum<T> is required, because instantiating |
| 62 | // std::underlying_type_t<T> when T is not an enum is UB prior to C++20. |
| 63 | template <typename T, bool = std::is_enum<T>::value> |
| 64 | struct IsScopedEnumImpl : std::false_type {}; |
| 65 | |
| 66 | template <typename T> |
| 67 | struct IsScopedEnumImpl<T, /*std::is_enum<T>::value=*/true> |
Avi Drissman | c109efd | 2022-04-27 22:03:35 | [diff] [blame] | 68 | : std::negation<std::is_convertible<T, std::underlying_type_t<T>>> {}; |
Jan Wilken Dörrie | f89fc2ac | 2021-03-05 06:51:22 | [diff] [blame] | 69 | |
| 70 | } // namespace internal |
| 71 | |
| 72 | // Implementation of C++23's std::is_scoped_enum |
| 73 | // |
| 74 | // Reference: https://en.cppreference.com/w/cpp/types/is_scoped_enum |
| 75 | template <typename T> |
| 76 | struct is_scoped_enum : internal::IsScopedEnumImpl<T> {}; |
| 77 | |
Jan Wilken Dörrie | 94bb5bc | 2021-03-22 18:37:40 | [diff] [blame] | 78 | // Implementation of C++20's std::remove_cvref. |
| 79 | // |
| 80 | // References: |
| 81 | // - https://en.cppreference.com/w/cpp/types/remove_cvref |
| 82 | // - https://wg21.link/meta.trans.other#lib:remove_cvref |
| 83 | template <typename T> |
| 84 | struct remove_cvref { |
| 85 | using type = std::remove_cv_t<std::remove_reference_t<T>>; |
| 86 | }; |
| 87 | |
| 88 | // Implementation of C++20's std::remove_cvref_t. |
| 89 | // |
| 90 | // References: |
| 91 | // - https://en.cppreference.com/w/cpp/types/remove_cvref |
| 92 | // - https://wg21.link/meta.type.synop#lib:remove_cvref_t |
| 93 | template <typename T> |
| 94 | using remove_cvref_t = typename remove_cvref<T>::type; |
| 95 | |
Jan Wilken Dörrie | 9f8955f | 2020-09-16 10:27:18 | [diff] [blame] | 96 | // Simplified implementation of C++20's std::iter_value_t. |
| 97 | // As opposed to std::iter_value_t, this implementation does not restrict |
| 98 | // the type of `Iter` and does not consider specializations of |
| 99 | // `indirectly_readable_traits`. |
| 100 | // |
| 101 | // Reference: https://wg21.link/readable.traits#2 |
| 102 | template <typename Iter> |
danakj | 6948b872 | 2022-05-04 14:02:04 | [diff] [blame] | 103 | struct IterValueImpl { |
| 104 | using value_type = typename std::iterator_traits<Iter>::value_type; |
| 105 | }; |
| 106 | |
| 107 | template <typename T, bool Cond = false> |
| 108 | struct IterValuePointerImpl { |
| 109 | // The `iterator_traits<T*>::value_type` member is not defined if T is not an |
| 110 | // object in C++20. |
| 111 | }; |
| 112 | template <typename T> |
| 113 | struct IterValuePointerImpl<T*, true> { |
| 114 | using value_type = typename std::iterator_traits<T*>::value_type; |
| 115 | }; |
| 116 | |
| 117 | template <typename T> |
| 118 | struct IterValueImpl<T*> { |
| 119 | using value_type = |
| 120 | typename IterValuePointerImpl<T*, std::is_object_v<T>>::value_type; |
| 121 | }; |
| 122 | |
| 123 | template <typename Iter> |
| 124 | using iter_value_t = typename IterValueImpl<remove_cvref_t<Iter>>::value_type; |
Jan Wilken Dörrie | 9f8955f | 2020-09-16 10:27:18 | [diff] [blame] | 125 | |
| 126 | // Simplified implementation of C++20's std::iter_reference_t. |
| 127 | // As opposed to std::iter_reference_t, this implementation does not restrict |
| 128 | // the type of `Iter`. |
| 129 | // |
| 130 | // Reference: https://wg21.link/iterator.synopsis#:~:text=iter_reference_t |
| 131 | template <typename Iter> |
| 132 | using iter_reference_t = decltype(*std::declval<Iter&>()); |
| 133 | |
| 134 | // Simplified implementation of C++20's std::indirect_result_t. As opposed to |
| 135 | // std::indirect_result_t, this implementation does not restrict the type of |
| 136 | // `Func` and `Iters`. |
| 137 | // |
| 138 | // Reference: https://wg21.link/iterator.synopsis#:~:text=indirect_result_t |
| 139 | template <typename Func, typename... Iters> |
Avi Drissman | 67c3b1e | 2022-04-27 20:42:49 | [diff] [blame] | 140 | using indirect_result_t = |
| 141 | std::invoke_result_t<Func, iter_reference_t<Iters>...>; |
Jan Wilken Dörrie | 9f8955f | 2020-09-16 10:27:18 | [diff] [blame] | 142 | |
| 143 | // Simplified implementation of C++20's std::projected. As opposed to |
| 144 | // std::projected, this implementation does not explicitly restrict the type of |
| 145 | // `Iter` and `Proj`, but rather does so implicitly by requiring |
| 146 | // `indirect_result_t<Proj, Iter>` is a valid type. This is required for SFINAE |
| 147 | // friendliness. |
| 148 | // |
| 149 | // Reference: https://wg21.link/projected |
| 150 | template <typename Iter, |
| 151 | typename Proj, |
| 152 | typename IndirectResultT = indirect_result_t<Proj, Iter>> |
| 153 | struct projected { |
Jan Wilken Dörrie | 94bb5bc | 2021-03-22 18:37:40 | [diff] [blame] | 154 | using value_type = remove_cvref_t<IndirectResultT>; |
Jan Wilken Dörrie | 9f8955f | 2020-09-16 10:27:18 | [diff] [blame] | 155 | |
| 156 | IndirectResultT operator*() const; // not defined |
| 157 | }; |
| 158 | |
willchan@chromium.org | 951269b | 2010-06-15 19:39:24 | [diff] [blame] | 159 | } // namespace base |
| 160 | |
dpolukhin@chromium.org | 81e8ebf | 2010-09-16 07:59:27 | [diff] [blame] | 161 | #endif // BASE_TEMPLATE_UTIL_H_ |