33 KiB
33 KiB
<html lang="en">
<head>
</head>
</html>
LCOV - code coverage report | ||||||||||||||||||||||
![]() | ||||||||||||||||||||||
|
||||||||||||||||||||||
![]() |
Line data Source code 1 : #pragma once 2 : #ifndef C10_UTIL_CPP17_H_ 3 : #define C10_UTIL_CPP17_H_ 4 : 5 : #include <c10/macros/Macros.h> 6 : #include <cstdlib> 7 : #include <functional> 8 : #include <memory> 9 : #include <sstream> 10 : #include <string> 11 : #include <type_traits> 12 : #include <utility> 13 : 14 : #if !defined(__clang__) && !defined(_MSC_VER) && defined(__GNUC__) && \ 15 : __GNUC__ < 5 16 : #error \ 17 : "You're trying to build PyTorch with a too old version of GCC. We need GCC 5 or later." 18 : #endif 19 : 20 : #if defined(__clang__) && __clang_major__ < 4 21 : #error \ 22 : "You're trying to build PyTorch with a too old version of Clang. We need Clang 4 or later." 23 : #endif 24 : 25 : #if (defined(_MSC_VER) && (!defined(_MSVC_LANG) || _MSVC_LANG < 201703L)) || \ 26 : (!defined(_MSC_VER) && __cplusplus < 201703L) 27 : #error You need C++17 to compile PyTorch 28 : #endif 29 : 30 : #if defined(_WIN32) && (defined(min) || defined(max)) 31 : #error Macro clash with min and max -- define NOMINMAX when compiling your program on Windows 32 : #endif 33 : 34 : /* 35 : * This header adds some polyfills with C++17 functionality 36 : */ 37 : 38 : namespace c10 { 39 : 40 : // in c++17 std::result_of has been superceded by std::invoke_result. Since 41 : // c++20, std::result_of is removed. 42 : template <typename F, typename... args> 43 : #if defined(__cpp_lib_is_invocable) && __cpp_lib_is_invocable >= 201703L 44 : using invoke_result = typename std::invoke_result<F, args...>; 45 : #else 46 : using invoke_result = typename std::result_of<F && (args && ...)>; 47 : #endif 48 : 49 : template <typename F, typename... args> 50 : using invoke_result_t = typename invoke_result<F, args...>::type; 51 : 52 : // std::is_pod is deprecated in C++20, std::is_standard_layout and 53 : // std::is_trivial are introduced in C++11, std::conjunction has been introduced 54 : // in C++17. 55 : template <typename T> 56 : #if defined(__cpp_lib_logical_traits) && __cpp_lib_logical_traits >= 201510L 57 : using is_pod = std::conjunction<std::is_standard_layout<T>, std::is_trivial<T>>; 58 : #else 59 : using is_pod = std::is_pod<T>; 60 : #endif 61 : 62 : template <typename T> 63 : constexpr bool is_pod_v = is_pod<T>::value; 64 : 65 : namespace guts { 66 : 67 : template <typename Base, typename Child, typename... Args> 68 : typename std::enable_if< 69 : !std::is_array<Base>::value && !std::is_array<Child>::value && 70 : std::is_base_of<Base, Child>::value, 71 : std::unique_ptr<Base>>::type 72 : make_unique_base(Args&&... args) { 73 : return std::unique_ptr<Base>(new Child(std::forward<Args>(args)...)); 74 : } 75 : 76 : #if defined(__cpp_lib_logical_traits) && !(defined(_MSC_VER) && _MSC_VER < 1920) 77 : 78 : template <class... B> 79 : using conjunction = std::conjunction<B...>; 80 : template <class... B> 81 : using disjunction = std::disjunction<B...>; 82 : template <bool B> 83 : using bool_constant = std::bool_constant<B>; 84 : template <class B> 85 : using negation = std::negation<B>; 86 : 87 : #else 88 : 89 : // Implementation taken from http://en.cppreference.com/w/cpp/types/conjunction 90 : template <class...> 91 : struct conjunction : std::true_type {}; 92 : template <class B1> 93 : struct conjunction<B1> : B1 {}; 94 : template <class B1, class... Bn> 95 : struct conjunction<B1, Bn...> 96 : : std::conditional_t<bool(B1::value), conjunction<Bn...>, B1> {}; 97 : 98 : // Implementation taken from http://en.cppreference.com/w/cpp/types/disjunction 99 : template <class...> 100 : struct disjunction : std::false_type {}; 101 : template <class B1> 102 : struct disjunction<B1> : B1 {}; 103 : template <class B1, class... Bn> 104 : struct disjunction<B1, Bn...> 105 : : std::conditional_t<bool(B1::value), B1, disjunction<Bn...>> {}; 106 : 107 : // Implementation taken from 108 : // http://en.cppreference.com/w/cpp/types/integral_constant 109 : template <bool B> 110 : using bool_constant = std::integral_constant<bool, B>; 111 : 112 : // Implementation taken from http://en.cppreference.com/w/cpp/types/negation 113 : template <class B> 114 : struct negation : bool_constant<!bool(B::value)> {}; 115 : 116 : #endif 117 : 118 : #ifdef __cpp_lib_void_t 119 : 120 : template <class T> 121 : using void_t = std::void_t<T>; 122 : 123 : #else 124 : 125 : // Implementation taken from http://en.cppreference.com/w/cpp/types/void_t 126 : // (it takes CWG1558 into account and also works for older compilers) 127 : template <typename... Ts> 128 : struct make_void { 129 : typedef void type; 130 : }; 131 : template <typename... Ts> 132 : using void_t = typename make_void<Ts...>::type; 133 : 134 : #endif 135 : 136 : #if defined(USE_ROCM) 137 : // rocm doesn't like the C10_HOST_DEVICE 138 : #define CUDA_HOST_DEVICE 139 : #else 140 : #define CUDA_HOST_DEVICE C10_HOST_DEVICE 141 : #endif 142 : 143 : #if defined(__cpp_lib_apply) && !defined(__CUDA_ARCH__) 144 : 145 : template <class F, class Tuple> 146 : CUDA_HOST_DEVICE inline constexpr decltype(auto) apply(F&& f, Tuple&& t) { 147 : return std::apply(std::forward<F>(f), std::forward<Tuple>(t)); 148 : } 149 : 150 : #else 151 : 152 : // Implementation from http://en.cppreference.com/w/cpp/utility/apply (but 153 : // modified) 154 : // TODO This is an incomplete implementation of std::apply, not working for 155 : // member functions. 156 : namespace detail { 157 : template <class F, class Tuple, std::size_t... INDEX> 158 : #if defined(_MSC_VER) 159 : // MSVC has a problem with the decltype() return type, but it also doesn't need 160 : // it 161 : C10_HOST_DEVICE constexpr auto apply_impl( 162 : F&& f, 163 : Tuple&& t, 164 : std::index_sequence<INDEX...>) 165 : #else 166 : // GCC/Clang need the decltype() return type 167 : CUDA_HOST_DEVICE constexpr decltype(auto) apply_impl( 168 : F&& f, 169 : Tuple&& t, 170 : std::index_sequence<INDEX...>) 171 : #endif 172 : { 173 : return std::forward<F>(f)(std::get<INDEX>(std::forward<Tuple>(t))...); 174 : } 175 : } // namespace detail 176 : 177 : template <class F, class Tuple> 178 : CUDA_HOST_DEVICE constexpr decltype(auto) apply(F&& f, Tuple&& t) { 179 : return detail::apply_impl( 180 : std::forward<F>(f), 181 : std::forward<Tuple>(t), 182 : std::make_index_sequence< 183 : std::tuple_size<std::remove_reference_t<Tuple>>::value>{}); 184 : } 185 : 186 : #endif 187 : 188 : #undef CUDA_HOST_DEVICE 189 : 190 : template <typename Functor, typename... Args> 191 : typename std::enable_if< 192 : std::is_member_pointer<typename std::decay<Functor>::type>::value, 193 : typename c10::invoke_result_t<Functor, Args...>>::type 194 : invoke(Functor&& f, Args&&... args) { 195 : return std::mem_fn(std::forward<Functor>(f))(std::forward<Args>(args)...); 196 : } 197 : 198 : template <typename Functor, typename... Args> 199 : typename std::enable_if< 200 : !std::is_member_pointer<typename std::decay<Functor>::type>::value, 201 : typename c10::invoke_result_t<Functor, Args...>>::type 202 : invoke(Functor&& f, Args&&... args) { 203 : return std::forward<Functor>(f)(std::forward<Args>(args)...); 204 : } 205 : 206 : namespace detail { 207 : struct _identity final { 208 : template <class T> 209 : using type_identity = T; 210 : 211 : template <class T> 212 : decltype(auto) operator()(T&& arg) { 213 : return std::forward<T>(arg); 214 : } 215 : }; 216 : 217 : template <class Func, class Enable = void> 218 : struct function_takes_identity_argument : std::false_type {}; 219 : #if defined(_MSC_VER) 220 : // For some weird reason, MSVC shows a compiler error when using guts::void_t 221 : // instead of std::void_t. But we're only building on MSVC versions that have 222 : // std::void_t, so let's just use that one. 223 : template <class Func> 224 : struct function_takes_identity_argument< 225 : Func, 226 : std::void_t<decltype(std::declval<Func>()(_identity()))>> : std::true_type { 227 : }; 228 : #else 229 : template <class Func> 230 : struct function_takes_identity_argument< 231 : Func, 232 : void_t<decltype(std::declval<Func>()(_identity()))>> : std::true_type {}; 233 : #endif 234 : } // namespace detail 235 : 236 : // GCC 4.8 doesn't define std::to_string, even though that's in C++11. Let's 237 : // define it. 238 : namespace detail { 239 : class DummyClassForToString final {}; 240 : } // namespace detail 241 : } // namespace guts 242 : } // namespace c10 243 : namespace std { 244 : // We use SFINAE to detect if std::to_string exists for a type, but that only 245 : // works if the function name is defined. So let's define a std::to_string for a 246 : // dummy type. If you're getting an error here saying that this overload doesn't 247 : // match your std::to_string() call, then you're calling std::to_string() but 248 : // should be calling c10::guts::to_string(). 249 : inline std::string to_string(c10::guts::detail::DummyClassForToString) { 250 : return ""; 251 : } 252 : 253 : } // namespace std 254 : namespace c10 { 255 : namespace guts { 256 : namespace detail { 257 : 258 : template <class T, class Enable = void> 259 : struct to_string_ final { 260 : static std::string call(T value) { 261 : std::ostringstream str; 262 : str << value; 263 : return str.str(); 264 : } 265 : }; 266 : // If a std::to_string exists, use that instead 267 : template <class T> 268 : struct to_string_<T, void_t<decltype(std::to_string(std::declval<T>()))>> 269 : final { 270 0 : static std::string call(T value) { 271 0 : return std::to_string(value); 272 : } 273 : }; 274 : } // namespace detail 275 : template <class T> 276 0 : inline std::string to_string(T value) { 277 0 : return detail::to_string_<T>::call(value); 278 : } 279 : 280 : } // namespace guts 281 : } // namespace c10 282 : 283 : #endif // C10_UTIL_CPP17_H_ |
![]() |
Generated by: LCOV version 2.0-1 |
</html>