#pragma once #ifndef C10_UTIL_CPP17_H_ #define C10_UTIL_CPP17_H_ #include #include #include #include #include #if !defined(__clang__) && !defined(_MSC_VER) && defined(__GNUC__) && \ __GNUC__ < 9 #error \ "You're trying to build PyTorch with a too old version of GCC. We need GCC 9 or later." #endif #if defined(__clang__) && __clang_major__ < 9 #error \ "You're trying to build PyTorch with a too old version of Clang. We need Clang 9 or later." #endif #if (defined(_MSC_VER) && (!defined(_MSVC_LANG) || _MSVC_LANG < 201703L)) || \ (!defined(_MSC_VER) && __cplusplus < 201703L) #error You need C++17 to compile PyTorch #endif #if defined(_WIN32) && (defined(min) || defined(max)) #error Macro clash with min and max -- define NOMINMAX when compiling your program on Windows #endif /* * This header adds some polyfills with C++17 functionality */ namespace c10 { // std::is_pod is deprecated in C++20, std::is_standard_layout and // std::is_trivial are introduced in C++11, std::conjunction has been introduced // in C++17. template using is_pod = std::conjunction, std::is_trivial>; template constexpr bool is_pod_v = is_pod::value; namespace guts { template std::enable_if_t< !std::is_array_v && !std::is_array_v && std::is_base_of_v, std::unique_ptr> make_unique_base(Args&&... args) { return std::unique_ptr(new Child(std::forward(args)...)); } #if defined(__cpp_lib_apply) && !defined(__CUDA_ARCH__) && !defined(__HIP__) template C10_HOST_DEVICE inline constexpr decltype(auto) apply(F&& f, Tuple&& t) { return std::apply(std::forward(f), std::forward(t)); } #else // Implementation from http://en.cppreference.com/w/cpp/utility/apply (but // modified) // TODO This is an incomplete implementation of std::apply, not working for // member functions. namespace detail { template #if defined(_MSC_VER) // MSVC has a problem with the decltype() return type, but it also doesn't need // it C10_HOST_DEVICE constexpr auto apply_impl( F&& f, Tuple&& t, std::index_sequence) #else // GCC/Clang need the decltype() return type C10_HOST_DEVICE constexpr decltype(auto) apply_impl( F&& f, Tuple&& t, std::index_sequence) #endif { return std::forward(f)(std::get(std::forward(t))...); } } // namespace detail template C10_HOST_DEVICE constexpr decltype(auto) apply(F&& f, Tuple&& t) { return detail::apply_impl( std::forward(f), std::forward(t), std::make_index_sequence< std::tuple_size>::value>{}); } #endif template std::enable_if_t< std::is_member_pointer_v>, typename std::invoke_result_t> invoke(Functor&& f, Args&&... args) { return std::mem_fn(std::forward(f))(std::forward(args)...); } template std::enable_if_t< !std::is_member_pointer_v>, typename std::invoke_result_t> invoke(Functor&& f, Args&&... args) { return std::forward(f)(std::forward(args)...); } namespace detail { struct _identity final { template using type_identity = T; template decltype(auto) operator()(T&& arg) { return std::forward(arg); } }; template struct function_takes_identity_argument : std::false_type {}; template struct function_takes_identity_argument< Func, std::void_t()(_identity()))>> : std::true_type { }; } // namespace detail } // namespace guts } // namespace c10 #endif // C10_UTIL_CPP17_H_