• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2014 Marshall A. Greenblatt. Portions copyright (c) 2011
2 // Google Inc. All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 //    * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 //    * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer
12 // in the documentation and/or other materials provided with the
13 // distribution.
14 //    * Neither the name of Google Inc. nor the name Chromium Embedded
15 // Framework nor the names of its contributors may be used to endorse
16 // or promote products derived from this software without specific prior
17 // written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
31 #ifndef CEF_INCLUDE_BASE_CEF_TEMPLATE_UTIL_H_
32 #define CEF_INCLUDE_BASE_CEF_TEMPLATE_UTIL_H_
33 #pragma once
34 
35 #if defined(USING_CHROMIUM_INCLUDES)
36 // When building CEF include the Chromium header directly.
37 #include "base/template_util.h"
38 #else  // !USING_CHROMIUM_INCLUDES
39 // The following is substantially similar to the Chromium implementation.
40 // If the Chromium implementation diverges the below implementation should be
41 // updated to match.
42 
43 #include <stddef.h>
44 #include <iosfwd>
45 #include <iterator>
46 #include <type_traits>
47 #include <utility>
48 #include <vector>
49 
50 #include "include/base/cef_build.h"
51 
52 // Some versions of libstdc++ have partial support for type_traits, but misses
53 // a smaller subset while removing some of the older non-standard stuff. Assume
54 // that all versions below 5.0 fall in this category, along with one 5.0
55 // experimental release. Test for this by consulting compiler major version,
56 // the only reliable option available, so theoretically this could fail should
57 // you attempt to mix an earlier version of libstdc++ with >= GCC5. But
58 // that's unlikely to work out, especially as GCC5 changed ABI.
59 #define CR_GLIBCXX_5_0_0 20150123
60 #if (defined(__GNUC__) && __GNUC__ < 5) || \
61     (defined(__GLIBCXX__) && __GLIBCXX__ == CR_GLIBCXX_5_0_0)
62 #define CR_USE_FALLBACKS_FOR_OLD_EXPERIMENTAL_GLIBCXX
63 #endif
64 
65 // This hacks around using gcc with libc++ which has some incompatibilies.
66 // - is_trivially_* doesn't work: https://llvm.org/bugs/show_bug.cgi?id=27538
67 // TODO(danakj): Remove this when android builders are all using a newer version
68 // of gcc, or the android ndk is updated to a newer libc++ that works with older
69 // gcc versions.
70 #if !defined(__clang__) && defined(_LIBCPP_VERSION)
71 #define CR_USE_FALLBACKS_FOR_GCC_WITH_LIBCXX
72 #endif
73 
74 namespace base {
75 
76 template <class T> struct is_non_const_reference : std::false_type {};
77 template <class T> struct is_non_const_reference<T&> : std::true_type {};
78 template <class T> struct is_non_const_reference<const T&> : std::false_type {};
79 
80 namespace internal {
81 
82 // Implementation detail of base::void_t below.
83 template <typename...>
84 struct make_void {
85   using type = void;
86 };
87 
88 }  // namespace internal
89 
90 // base::void_t is an implementation of std::void_t from C++17.
91 //
92 // We use |base::internal::make_void| as a helper struct to avoid a C++14
93 // defect:
94 //   http://en.cppreference.com/w/cpp/types/void_t
95 //   http://open-std.org/JTC1/SC22/WG21/docs/cwg_defects.html#1558
96 template <typename... Ts>
97 using void_t = typename ::base::internal::make_void<Ts...>::type;
98 
99 namespace internal {
100 
101 // Uses expression SFINAE to detect whether using operator<< would work.
102 template <typename T, typename = void>
103 struct SupportsOstreamOperator : std::false_type {};
104 template <typename T>
105 struct SupportsOstreamOperator<T,
106                                decltype(void(std::declval<std::ostream&>()
107                                              << std::declval<T>()))>
108     : std::true_type {};
109 
110 template <typename T, typename = void>
111 struct SupportsToString : std::false_type {};
112 template <typename T>
113 struct SupportsToString<T, decltype(void(std::declval<T>().ToString()))>
114     : std::true_type {};
115 
116 // Used to detech whether the given type is an iterator.  This is normally used
117 // with std::enable_if to provide disambiguation for functions that take
118 // templatzed iterators as input.
119 template <typename T, typename = void>
120 struct is_iterator : std::false_type {};
121 
122 template <typename T>
123 struct is_iterator<T,
124                    void_t<typename std::iterator_traits<T>::iterator_category>>
125     : std::true_type {};
126 
127 // Helper to express preferences in an overload set. If more than one overload
128 // are available for a given set of parameters the overload with the higher
129 // priority will be chosen.
130 template <size_t I>
131 struct priority_tag : priority_tag<I - 1> {};
132 
133 template <>
134 struct priority_tag<0> {};
135 
136 }  // namespace internal
137 
138 // is_trivially_copyable is especially hard to get right.
139 // - Older versions of libstdc++ will fail to have it like they do for other
140 //   type traits. This has become a subset of the second point, but used to be
141 //   handled independently.
142 // - An experimental release of gcc includes most of type_traits but misses
143 //   is_trivially_copyable, so we still have to avoid using libstdc++ in this
144 //   case, which is covered by CR_USE_FALLBACKS_FOR_OLD_EXPERIMENTAL_GLIBCXX.
145 // - When compiling libc++ from before r239653, with a gcc compiler, the
146 //   std::is_trivially_copyable can fail. So we need to work around that by not
147 //   using the one in libc++ in this case. This is covered by the
148 //   CR_USE_FALLBACKS_FOR_GCC_WITH_LIBCXX define, and is discussed in
149 //   https://llvm.org/bugs/show_bug.cgi?id=27538#c1 where they point out that
150 //   in libc++'s commit r239653 this is fixed by libc++ checking for gcc 5.1.
151 // - In both of the above cases we are using the gcc compiler. When defining
152 //   this ourselves on compiler intrinsics, the __is_trivially_copyable()
153 //   intrinsic is not available on gcc before version 5.1 (see the discussion in
154 //   https://llvm.org/bugs/show_bug.cgi?id=27538#c1 again), so we must check for
155 //   that version.
156 // - When __is_trivially_copyable() is not available because we are on gcc older
157 //   than 5.1, we need to fall back to something, so we use __has_trivial_copy()
158 //   instead based on what was done one-off in bit_cast() previously.
159 
160 // TODO(crbug.com/554293): Remove this when all platforms have this in the std
161 // namespace and it works with gcc as needed.
162 #if defined(CR_USE_FALLBACKS_FOR_OLD_EXPERIMENTAL_GLIBCXX) || \
163     defined(CR_USE_FALLBACKS_FOR_GCC_WITH_LIBCXX)
164 template <typename T>
165 struct is_trivially_copyable {
166 // TODO(danakj): Remove this when android builders are all using a newer version
167 // of gcc, or the android ndk is updated to a newer libc++ that does this for
168 // us.
169 #if _GNUC_VER >= 501
170   static constexpr bool value = __is_trivially_copyable(T);
171 #else
172   static constexpr bool value =
173       __has_trivial_copy(T) && __has_trivial_destructor(T);
174 #endif
175 };
176 #else
177 template <class T>
178 using is_trivially_copyable = std::is_trivially_copyable<T>;
179 #endif
180 
181 #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ <= 7
182 // Workaround for g++7 and earlier family.
183 // Due to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80654, without this
184 // Optional<std::vector<T>> where T is non-copyable causes a compile error.
185 // As we know it is not trivially copy constructible, explicitly declare so.
186 template <typename T>
187 struct is_trivially_copy_constructible
188     : std::is_trivially_copy_constructible<T> {};
189 
190 template <typename... T>
191 struct is_trivially_copy_constructible<std::vector<T...>> : std::false_type {};
192 #else
193 // Otherwise use std::is_trivially_copy_constructible as is.
194 template <typename T>
195 using is_trivially_copy_constructible = std::is_trivially_copy_constructible<T>;
196 #endif
197 
198 // base::in_place_t is an implementation of std::in_place_t from
199 // C++17. A tag type used to request in-place construction in template vararg
200 // constructors.
201 
202 // Specification:
203 // https://en.cppreference.com/w/cpp/utility/in_place
204 struct in_place_t {};
205 constexpr in_place_t in_place = {};
206 
207 // base::in_place_type_t is an implementation of std::in_place_type_t from
208 // C++17. A tag type used for in-place construction when the type to construct
209 // needs to be specified, such as with base::unique_any, designed to be a
210 // drop-in replacement.
211 
212 // Specification:
213 // http://en.cppreference.com/w/cpp/utility/in_place
214 template <typename T>
215 struct in_place_type_t {};
216 
217 template <typename T>
218 struct is_in_place_type_t {
219   static constexpr bool value = false;
220 };
221 
222 template <typename... Ts>
223 struct is_in_place_type_t<in_place_type_t<Ts...>> {
224   static constexpr bool value = true;
225 };
226 
227 // C++14 implementation of C++17's std::bool_constant.
228 //
229 // Reference: https://en.cppreference.com/w/cpp/types/integral_constant
230 // Specification: https://wg21.link/meta.type.synop
231 template <bool B>
232 using bool_constant = std::integral_constant<bool, B>;
233 
234 // C++14 implementation of C++17's std::conjunction.
235 //
236 // Reference: https://en.cppreference.com/w/cpp/types/conjunction
237 // Specification: https://wg21.link/meta.logical#1.itemdecl:1
238 template <typename...>
239 struct conjunction : std::true_type {};
240 
241 template <typename B1>
242 struct conjunction<B1> : B1 {};
243 
244 template <typename B1, typename... Bn>
245 struct conjunction<B1, Bn...>
246     : std::conditional_t<static_cast<bool>(B1::value), conjunction<Bn...>, B1> {
247 };
248 
249 // C++14 implementation of C++17's std::disjunction.
250 //
251 // Reference: https://en.cppreference.com/w/cpp/types/disjunction
252 // Specification: https://wg21.link/meta.logical#itemdecl:2
253 template <typename...>
254 struct disjunction : std::false_type {};
255 
256 template <typename B1>
257 struct disjunction<B1> : B1 {};
258 
259 template <typename B1, typename... Bn>
260 struct disjunction<B1, Bn...>
261     : std::conditional_t<static_cast<bool>(B1::value), B1, disjunction<Bn...>> {
262 };
263 
264 // C++14 implementation of C++17's std::negation.
265 //
266 // Reference: https://en.cppreference.com/w/cpp/types/negation
267 // Specification: https://wg21.link/meta.logical#itemdecl:3
268 template <typename B>
269 struct negation : bool_constant<!static_cast<bool>(B::value)> {};
270 
271 // Implementation of C++17's invoke_result.
272 //
273 // This implementation adds references to `Functor` and `Args` to work around
274 // some quirks of std::result_of. See the #Notes section of [1] for details.
275 //
276 // References:
277 // [1] https://en.cppreference.com/w/cpp/types/result_of
278 // [2] https://wg21.link/meta.trans.other#lib:invoke_result
279 #if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L)
280 template <typename Functor, typename... Args>
281 using invoke_result = std::invoke_result<Functor, Args...>;
282 #else
283 template <typename Functor, typename... Args>
284 using invoke_result = std::result_of<Functor && (Args && ...)>;
285 #endif
286 
287 // Implementation of C++17's std::invoke_result_t.
288 //
289 // Reference: https://wg21.link/meta.type.synop#lib:invoke_result_t
290 template <typename Functor, typename... Args>
291 using invoke_result_t = typename invoke_result<Functor, Args...>::type;
292 
293 namespace internal {
294 
295 // Base case, `InvokeResult` does not have a nested type member. This means `F`
296 // could not be invoked with `Args...` and thus is not invocable.
297 template <typename InvokeResult, typename R, typename = void>
298 struct IsInvocableImpl : std::false_type {};
299 
300 // Happy case, `InvokeResult` does have a nested type member. Now check whether
301 // `InvokeResult::type` is convertible to `R`. Short circuit in case
302 // `std::is_void<R>`.
303 template <typename InvokeResult, typename R>
304 struct IsInvocableImpl<InvokeResult, R, void_t<typename InvokeResult::type>>
305     : disjunction<std::is_void<R>,
306                   std::is_convertible<typename InvokeResult::type, R>> {};
307 
308 }  // namespace internal
309 
310 // Implementation of C++17's std::is_invocable_r.
311 //
312 // Returns whether `F` can be invoked with `Args...` and the result is
313 // convertible to `R`.
314 //
315 // Reference: https://wg21.link/meta.rel#lib:is_invocable_r
316 template <typename R, typename F, typename... Args>
317 struct is_invocable_r
318     : internal::IsInvocableImpl<invoke_result<F, Args...>, R> {};
319 
320 // Implementation of C++17's std::is_invocable.
321 //
322 // Returns whether `F` can be invoked with `Args...`.
323 //
324 // Reference: https://wg21.link/meta.rel#lib:is_invocable
325 template <typename F, typename... Args>
326 struct is_invocable : is_invocable_r<void, F, Args...> {};
327 
328 namespace internal {
329 
330 // The indirection with std::is_enum<T> is required, because instantiating
331 // std::underlying_type_t<T> when T is not an enum is UB prior to C++20.
332 template <typename T, bool = std::is_enum<T>::value>
333 struct IsScopedEnumImpl : std::false_type {};
334 
335 template <typename T>
336 struct IsScopedEnumImpl<T, /*std::is_enum<T>::value=*/true>
337     : negation<std::is_convertible<T, std::underlying_type_t<T>>> {};
338 
339 }  // namespace internal
340 
341 // Implementation of C++23's std::is_scoped_enum
342 //
343 // Reference: https://en.cppreference.com/w/cpp/types/is_scoped_enum
344 template <typename T>
345 struct is_scoped_enum : internal::IsScopedEnumImpl<T> {};
346 
347 // Implementation of C++20's std::remove_cvref.
348 //
349 // References:
350 // - https://en.cppreference.com/w/cpp/types/remove_cvref
351 // - https://wg21.link/meta.trans.other#lib:remove_cvref
352 template <typename T>
353 struct remove_cvref {
354   using type = std::remove_cv_t<std::remove_reference_t<T>>;
355 };
356 
357 // Implementation of C++20's std::remove_cvref_t.
358 //
359 // References:
360 // - https://en.cppreference.com/w/cpp/types/remove_cvref
361 // - https://wg21.link/meta.type.synop#lib:remove_cvref_t
362 template <typename T>
363 using remove_cvref_t = typename remove_cvref<T>::type;
364 
365 // Simplified implementation of C++20's std::iter_value_t.
366 // As opposed to std::iter_value_t, this implementation does not restrict
367 // the type of `Iter` and does not consider specializations of
368 // `indirectly_readable_traits`.
369 //
370 // Reference: https://wg21.link/readable.traits#2
371 template <typename Iter>
372 using iter_value_t =
373     typename std::iterator_traits<remove_cvref_t<Iter>>::value_type;
374 
375 // Simplified implementation of C++20's std::iter_reference_t.
376 // As opposed to std::iter_reference_t, this implementation does not restrict
377 // the type of `Iter`.
378 //
379 // Reference: https://wg21.link/iterator.synopsis#:~:text=iter_reference_t
380 template <typename Iter>
381 using iter_reference_t = decltype(*std::declval<Iter&>());
382 
383 // Simplified implementation of C++20's std::indirect_result_t. As opposed to
384 // std::indirect_result_t, this implementation does not restrict the type of
385 // `Func` and `Iters`.
386 //
387 // Reference: https://wg21.link/iterator.synopsis#:~:text=indirect_result_t
388 template <typename Func, typename... Iters>
389 using indirect_result_t = invoke_result_t<Func, iter_reference_t<Iters>...>;
390 
391 // Simplified implementation of C++20's std::projected. As opposed to
392 // std::projected, this implementation does not explicitly restrict the type of
393 // `Iter` and `Proj`, but rather does so implicitly by requiring
394 // `indirect_result_t<Proj, Iter>` is a valid type. This is required for SFINAE
395 // friendliness.
396 //
397 // Reference: https://wg21.link/projected
398 template <typename Iter,
399           typename Proj,
400           typename IndirectResultT = indirect_result_t<Proj, Iter>>
401 struct projected {
402   using value_type = remove_cvref_t<IndirectResultT>;
403 
404   IndirectResultT operator*() const;  // not defined
405 };
406 
407 }  // namespace base
408 
409 #undef CR_USE_FALLBACKS_FOR_GCC_WITH_LIBCXX
410 #undef CR_USE_FALLBACKS_FOR_OLD_EXPERIMENTAL_GLIBCXX
411 
412 #endif  // !USING_CHROMIUM_INCLUDES
413 
414 #endif  // CEF_INCLUDE_BASE_CEF_TEMPLATE_UTIL_H_
415