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 5 #ifndef BASE_TEMPLATE_UTIL_H_ 6 #define BASE_TEMPLATE_UTIL_H_ 7 8 #include <stddef.h> 9 #include <iosfwd> 10 #include <iterator> 11 #include <type_traits> 12 #include <utility> 13 #include <vector> 14 15 #include "build/build_config.h" 16 17 // Some versions of libstdc++ have partial support for type_traits, but misses 18 // a smaller subset while removing some of the older non-standard stuff. Assume 19 // that all versions below 5.0 fall in this category, along with one 5.0 20 // experimental release. Test for this by consulting compiler major version, 21 // the only reliable option available, so theoretically this could fail should 22 // you attempt to mix an earlier version of libstdc++ with >= GCC5. But 23 // that's unlikely to work out, especially as GCC5 changed ABI. 24 #define CR_GLIBCXX_5_0_0 20150123 25 #if (defined(__GNUC__) && __GNUC__ < 5) || \ 26 (defined(__GLIBCXX__) && __GLIBCXX__ == CR_GLIBCXX_5_0_0) 27 #define CR_USE_FALLBACKS_FOR_OLD_EXPERIMENTAL_GLIBCXX 28 #endif 29 30 // This hacks around using gcc with libc++ which has some incompatibilies. 31 // - is_trivially_* doesn't work: https://llvm.org/bugs/show_bug.cgi?id=27538 32 // TODO(danakj): Remove this when android builders are all using a newer version 33 // of gcc, or the android ndk is updated to a newer libc++ that works with older 34 // gcc versions. 35 #if !defined(__clang__) && defined(_LIBCPP_VERSION) 36 #define CR_USE_FALLBACKS_FOR_GCC_WITH_LIBCXX 37 #endif 38 39 namespace base { 40 41 template <class T> struct is_non_const_reference : std::false_type {}; 42 template <class T> struct is_non_const_reference<T&> : std::true_type {}; 43 template <class T> struct is_non_const_reference<const T&> : std::false_type {}; 44 45 namespace internal { 46 47 // Implementation detail of base::void_t below. 48 template <typename...> 49 struct make_void { 50 using type = void; 51 }; 52 53 } // namespace internal 54 55 // base::void_t is an implementation of std::void_t from C++17. 56 // 57 // We use |base::internal::make_void| as a helper struct to avoid a C++14 58 // defect: 59 // http://en.cppreference.com/w/cpp/types/void_t 60 // http://open-std.org/JTC1/SC22/WG21/docs/cwg_defects.html#1558 61 template <typename... Ts> 62 using void_t = typename ::base::internal::make_void<Ts...>::type; 63 64 namespace internal { 65 66 // Uses expression SFINAE to detect whether using operator<< would work. 67 template <typename T, typename = void> 68 struct SupportsOstreamOperator : std::false_type {}; 69 template <typename T> 70 struct SupportsOstreamOperator<T, 71 decltype(void(std::declval<std::ostream&>() 72 << std::declval<T>()))> 73 : std::true_type {}; 74 75 template <typename T, typename = void> 76 struct SupportsToString : std::false_type {}; 77 template <typename T> 78 struct SupportsToString<T, decltype(void(std::declval<T>().ToString()))> 79 : std::true_type {}; 80 81 // Used to detech whether the given type is an iterator. This is normally used 82 // with std::enable_if to provide disambiguation for functions that take 83 // templatzed iterators as input. 84 template <typename T, typename = void> 85 struct is_iterator : std::false_type {}; 86 87 template <typename T> 88 struct is_iterator<T, 89 void_t<typename std::iterator_traits<T>::iterator_category>> 90 : std::true_type {}; 91 92 // Helper to express preferences in an overload set. If more than one overload 93 // are available for a given set of parameters the overload with the higher 94 // priority will be chosen. 95 template <size_t I> 96 struct priority_tag : priority_tag<I - 1> {}; 97 98 template <> 99 struct priority_tag<0> {}; 100 101 } // namespace internal 102 103 // is_trivially_copyable is especially hard to get right. 104 // - Older versions of libstdc++ will fail to have it like they do for other 105 // type traits. This has become a subset of the second point, but used to be 106 // handled independently. 107 // - An experimental release of gcc includes most of type_traits but misses 108 // is_trivially_copyable, so we still have to avoid using libstdc++ in this 109 // case, which is covered by CR_USE_FALLBACKS_FOR_OLD_EXPERIMENTAL_GLIBCXX. 110 // - When compiling libc++ from before r239653, with a gcc compiler, the 111 // std::is_trivially_copyable can fail. So we need to work around that by not 112 // using the one in libc++ in this case. This is covered by the 113 // CR_USE_FALLBACKS_FOR_GCC_WITH_LIBCXX define, and is discussed in 114 // https://llvm.org/bugs/show_bug.cgi?id=27538#c1 where they point out that 115 // in libc++'s commit r239653 this is fixed by libc++ checking for gcc 5.1. 116 // - In both of the above cases we are using the gcc compiler. When defining 117 // this ourselves on compiler intrinsics, the __is_trivially_copyable() 118 // intrinsic is not available on gcc before version 5.1 (see the discussion in 119 // https://llvm.org/bugs/show_bug.cgi?id=27538#c1 again), so we must check for 120 // that version. 121 // - When __is_trivially_copyable() is not available because we are on gcc older 122 // than 5.1, we need to fall back to something, so we use __has_trivial_copy() 123 // instead based on what was done one-off in bit_cast() previously. 124 125 // TODO(crbug.com/554293): Remove this when all platforms have this in the std 126 // namespace and it works with gcc as needed. 127 #if defined(CR_USE_FALLBACKS_FOR_OLD_EXPERIMENTAL_GLIBCXX) || \ 128 defined(CR_USE_FALLBACKS_FOR_GCC_WITH_LIBCXX) 129 template <typename T> 130 struct is_trivially_copyable { 131 // TODO(danakj): Remove this when android builders are all using a newer version 132 // of gcc, or the android ndk is updated to a newer libc++ that does this for 133 // us. 134 #if _GNUC_VER >= 501 135 static constexpr bool value = __is_trivially_copyable(T); 136 #else 137 static constexpr bool value = 138 __has_trivial_copy(T) && __has_trivial_destructor(T); 139 #endif 140 }; 141 #else 142 template <class T> 143 using is_trivially_copyable = std::is_trivially_copyable<T>; 144 #endif 145 146 #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ <= 7 147 // Workaround for g++7 and earlier family. 148 // Due to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80654, without this 149 // Optional<std::vector<T>> where T is non-copyable causes a compile error. 150 // As we know it is not trivially copy constructible, explicitly declare so. 151 template <typename T> 152 struct is_trivially_copy_constructible 153 : std::is_trivially_copy_constructible<T> {}; 154 155 template <typename... T> 156 struct is_trivially_copy_constructible<std::vector<T...>> : std::false_type {}; 157 #else 158 // Otherwise use std::is_trivially_copy_constructible as is. 159 template <typename T> 160 using is_trivially_copy_constructible = std::is_trivially_copy_constructible<T>; 161 #endif 162 163 // base::in_place_t is an implementation of std::in_place_t from 164 // C++17. A tag type used to request in-place construction in template vararg 165 // constructors. 166 167 // Specification: 168 // https://en.cppreference.com/w/cpp/utility/in_place 169 struct in_place_t {}; 170 constexpr in_place_t in_place = {}; 171 172 // base::in_place_type_t is an implementation of std::in_place_type_t from 173 // C++17. A tag type used for in-place construction when the type to construct 174 // needs to be specified, such as with base::unique_any, designed to be a 175 // drop-in replacement. 176 177 // Specification: 178 // http://en.cppreference.com/w/cpp/utility/in_place 179 template <typename T> 180 struct in_place_type_t {}; 181 182 template <typename T> 183 struct is_in_place_type_t { 184 static constexpr bool value = false; 185 }; 186 187 template <typename... Ts> 188 struct is_in_place_type_t<in_place_type_t<Ts...>> { 189 static constexpr bool value = true; 190 }; 191 192 // C++14 implementation of C++17's std::bool_constant. 193 // 194 // Reference: https://en.cppreference.com/w/cpp/types/integral_constant 195 // Specification: https://wg21.link/meta.type.synop 196 template <bool B> 197 using bool_constant = std::integral_constant<bool, B>; 198 199 // C++14 implementation of C++17's std::conjunction. 200 // 201 // Reference: https://en.cppreference.com/w/cpp/types/conjunction 202 // Specification: https://wg21.link/meta.logical#1.itemdecl:1 203 template <typename...> 204 struct conjunction : std::true_type {}; 205 206 template <typename B1> 207 struct conjunction<B1> : B1 {}; 208 209 template <typename B1, typename... Bn> 210 struct conjunction<B1, Bn...> 211 : std::conditional_t<static_cast<bool>(B1::value), conjunction<Bn...>, B1> { 212 }; 213 214 // C++14 implementation of C++17's std::disjunction. 215 // 216 // Reference: https://en.cppreference.com/w/cpp/types/disjunction 217 // Specification: https://wg21.link/meta.logical#itemdecl:2 218 template <typename...> 219 struct disjunction : std::false_type {}; 220 221 template <typename B1> 222 struct disjunction<B1> : B1 {}; 223 224 template <typename B1, typename... Bn> 225 struct disjunction<B1, Bn...> 226 : std::conditional_t<static_cast<bool>(B1::value), B1, disjunction<Bn...>> { 227 }; 228 229 // C++14 implementation of C++17's std::negation. 230 // 231 // Reference: https://en.cppreference.com/w/cpp/types/negation 232 // Specification: https://wg21.link/meta.logical#itemdecl:3 233 template <typename B> 234 struct negation : bool_constant<!static_cast<bool>(B::value)> {}; 235 236 // Implementation of C++17's std::invoke_result_t. 237 // 238 // This implementation adds references to `Functor` and `Args` to work around 239 // some quirks of std::result_of_t. See the #Notes section of [1] for details. 240 // 241 // References: 242 // [1] https://en.cppreference.com/w/cpp/types/result_of 243 // [2] https://wg21.link/meta.type.synop#lib:invoke_result_t 244 template <typename Functor, typename... Args> 245 using invoke_result_t = std::result_of_t<Functor && (Args && ...)>; 246 247 // Simplified implementation of C++20's std::iter_value_t. 248 // As opposed to std::iter_value_t, this implementation does not restrict 249 // the type of `Iter` and does not consider specializations of 250 // `indirectly_readable_traits`. 251 // 252 // Reference: https://wg21.link/readable.traits#2 253 template <typename Iter> 254 using iter_value_t = typename std::iterator_traits< 255 std::remove_cv_t<std::remove_reference_t<Iter>>>::value_type; 256 257 // Simplified implementation of C++20's std::iter_reference_t. 258 // As opposed to std::iter_reference_t, this implementation does not restrict 259 // the type of `Iter`. 260 // 261 // Reference: https://wg21.link/iterator.synopsis#:~:text=iter_reference_t 262 template <typename Iter> 263 using iter_reference_t = decltype(*std::declval<Iter&>()); 264 265 // Simplified implementation of C++20's std::indirect_result_t. As opposed to 266 // std::indirect_result_t, this implementation does not restrict the type of 267 // `Func` and `Iters`. 268 // 269 // Reference: https://wg21.link/iterator.synopsis#:~:text=indirect_result_t 270 template <typename Func, typename... Iters> 271 using indirect_result_t = invoke_result_t<Func, iter_reference_t<Iters>...>; 272 273 // Simplified implementation of C++20's std::projected. As opposed to 274 // std::projected, this implementation does not explicitly restrict the type of 275 // `Iter` and `Proj`, but rather does so implicitly by requiring 276 // `indirect_result_t<Proj, Iter>` is a valid type. This is required for SFINAE 277 // friendliness. 278 // 279 // Reference: https://wg21.link/projected 280 template <typename Iter, 281 typename Proj, 282 typename IndirectResultT = indirect_result_t<Proj, Iter>> 283 struct projected { 284 using value_type = std::remove_cv_t<std::remove_reference_t<IndirectResultT>>; 285 286 IndirectResultT operator*() const; // not defined 287 }; 288 289 } // namespace base 290 291 #undef CR_USE_FALLBACKS_FOR_GCC_WITH_LIBCXX 292 #undef CR_USE_FALLBACKS_FOR_OLD_EXPERIMENTAL_GLIBCXX 293 294 #endif // BASE_TEMPLATE_UTIL_H_ 295