• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2011 The Chromium Authors
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_
7 
8 #include <stddef.h>
9 
10 #include <iosfwd>
11 #include <iterator>
12 #include <type_traits>
13 #include <utility>
14 
15 #include "base/compiler_specific.h"
16 
17 namespace base {
18 
19 namespace internal {
20 
21 template <typename T, typename = void>
22 struct SupportsToString : std::false_type {};
23 template <typename T>
24 struct SupportsToString<T, decltype(void(std::declval<T>().ToString()))>
25     : std::true_type {};
26 
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 
33 template <typename T>
34 struct is_iterator<
35     T,
36     std::void_t<typename std::iterator_traits<T>::iterator_category>>
37     : std::true_type {};
38 
39 // Helper to express preferences in an overload set. If more than one overload
40 // are available for a given set of parameters the overload with the higher
41 // priority will be chosen.
42 template <size_t I>
43 struct priority_tag : priority_tag<I - 1> {};
44 
45 template <>
46 struct priority_tag<0> {};
47 
48 }  // namespace internal
49 
50 namespace internal {
51 
52 // The indirection with std::is_enum<T> is required, because instantiating
53 // std::underlying_type_t<T> when T is not an enum is UB prior to C++20.
54 template <typename T, bool = std::is_enum<T>::value>
55 struct IsScopedEnumImpl : std::false_type {};
56 
57 template <typename T>
58 struct IsScopedEnumImpl<T, /*std::is_enum<T>::value=*/true>
59     : std::negation<std::is_convertible<T, std::underlying_type_t<T>>> {};
60 
61 }  // namespace internal
62 
63 // Implementation of C++23's std::is_scoped_enum
64 //
65 // Reference: https://en.cppreference.com/w/cpp/types/is_scoped_enum
66 template <typename T>
67 struct is_scoped_enum : internal::IsScopedEnumImpl<T> {};
68 
69 // Implementation of C++20's std::remove_cvref.
70 //
71 // References:
72 // - https://en.cppreference.com/w/cpp/types/remove_cvref
73 // - https://wg21.link/meta.trans.other#lib:remove_cvref
74 template <typename T>
75 struct remove_cvref {
76   using type = std::remove_cv_t<std::remove_reference_t<T>>;
77 };
78 
79 // Implementation of C++20's std::remove_cvref_t.
80 //
81 // References:
82 // - https://en.cppreference.com/w/cpp/types/remove_cvref
83 // - https://wg21.link/meta.type.synop#lib:remove_cvref_t
84 template <typename T>
85 using remove_cvref_t = typename remove_cvref<T>::type;
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 
98 template <typename T, bool Cond = false>
99 struct IterValuePointerImpl {
100   // The `iterator_traits<T*>::value_type` member is not defined if T is not an
101   // object in C++20.
102 };
103 template <typename T>
104 struct IterValuePointerImpl<T*, true> {
105   using value_type = typename std::iterator_traits<T*>::value_type;
106 };
107 
108 template <typename T>
109 struct IterValueImpl<T*> {
110   using value_type =
111       typename IterValuePointerImpl<T*, std::is_object_v<T>>::value_type;
112 };
113 
114 template <typename Iter>
115 using iter_value_t = typename IterValueImpl<remove_cvref_t<Iter>>::value_type;
116 
117 // Simplified implementation of C++20's std::iter_reference_t.
118 // As opposed to std::iter_reference_t, this implementation does not restrict
119 // the type of `Iter`.
120 //
121 // Reference: https://wg21.link/iterator.synopsis#:~:text=iter_reference_t
122 template <typename Iter>
123 using iter_reference_t = decltype(*std::declval<Iter&>());
124 
125 // Simplified implementation of C++20's std::indirect_result_t. As opposed to
126 // std::indirect_result_t, this implementation does not restrict the type of
127 // `Func` and `Iters`.
128 //
129 // Reference: https://wg21.link/iterator.synopsis#:~:text=indirect_result_t
130 template <typename Func, typename... Iters>
131 using indirect_result_t =
132     std::invoke_result_t<Func, iter_reference_t<Iters>...>;
133 
134 // Simplified implementation of C++20's std::projected. As opposed to
135 // std::projected, this implementation does not explicitly restrict the type of
136 // `Iter` and `Proj`, but rather does so implicitly by requiring
137 // `indirect_result_t<Proj, Iter>` is a valid type. This is required for SFINAE
138 // friendliness.
139 //
140 // Reference: https://wg21.link/projected
141 template <typename Iter,
142           typename Proj,
143           typename IndirectResultT = indirect_result_t<Proj, Iter>>
144 struct projected {
145   using value_type = remove_cvref_t<IndirectResultT>;
146 
147   IndirectResultT operator*() const;  // not defined
148 };
149 
150 }  // namespace base
151 
152 #endif  // BASE_TEMPLATE_UTIL_H_
153