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