1*da0073e9SAndroid Build Coastguard Worker #pragma once
2*da0073e9SAndroid Build Coastguard Worker #ifndef C10_UTIL_CPP17_H_
3*da0073e9SAndroid Build Coastguard Worker #define C10_UTIL_CPP17_H_
4*da0073e9SAndroid Build Coastguard Worker
5*da0073e9SAndroid Build Coastguard Worker #include <c10/macros/Macros.h>
6*da0073e9SAndroid Build Coastguard Worker #include <functional>
7*da0073e9SAndroid Build Coastguard Worker #include <memory>
8*da0073e9SAndroid Build Coastguard Worker #include <type_traits>
9*da0073e9SAndroid Build Coastguard Worker #include <utility>
10*da0073e9SAndroid Build Coastguard Worker
11*da0073e9SAndroid Build Coastguard Worker #if !defined(__clang__) && !defined(_MSC_VER) && defined(__GNUC__) && \
12*da0073e9SAndroid Build Coastguard Worker __GNUC__ < 9
13*da0073e9SAndroid Build Coastguard Worker #error \
14*da0073e9SAndroid Build Coastguard Worker "You're trying to build PyTorch with a too old version of GCC. We need GCC 9 or later."
15*da0073e9SAndroid Build Coastguard Worker #endif
16*da0073e9SAndroid Build Coastguard Worker
17*da0073e9SAndroid Build Coastguard Worker #if defined(__clang__) && __clang_major__ < 9
18*da0073e9SAndroid Build Coastguard Worker #error \
19*da0073e9SAndroid Build Coastguard Worker "You're trying to build PyTorch with a too old version of Clang. We need Clang 9 or later."
20*da0073e9SAndroid Build Coastguard Worker #endif
21*da0073e9SAndroid Build Coastguard Worker
22*da0073e9SAndroid Build Coastguard Worker #if (defined(_MSC_VER) && (!defined(_MSVC_LANG) || _MSVC_LANG < 201703L)) || \
23*da0073e9SAndroid Build Coastguard Worker (!defined(_MSC_VER) && __cplusplus < 201703L)
24*da0073e9SAndroid Build Coastguard Worker #error You need C++17 to compile PyTorch
25*da0073e9SAndroid Build Coastguard Worker #endif
26*da0073e9SAndroid Build Coastguard Worker
27*da0073e9SAndroid Build Coastguard Worker #if defined(_WIN32) && (defined(min) || defined(max))
28*da0073e9SAndroid Build Coastguard Worker #error Macro clash with min and max -- define NOMINMAX when compiling your program on Windows
29*da0073e9SAndroid Build Coastguard Worker #endif
30*da0073e9SAndroid Build Coastguard Worker
31*da0073e9SAndroid Build Coastguard Worker /*
32*da0073e9SAndroid Build Coastguard Worker * This header adds some polyfills with C++17 functionality
33*da0073e9SAndroid Build Coastguard Worker */
34*da0073e9SAndroid Build Coastguard Worker
35*da0073e9SAndroid Build Coastguard Worker namespace c10 {
36*da0073e9SAndroid Build Coastguard Worker
37*da0073e9SAndroid Build Coastguard Worker // std::is_pod is deprecated in C++20, std::is_standard_layout and
38*da0073e9SAndroid Build Coastguard Worker // std::is_trivial are introduced in C++11, std::conjunction has been introduced
39*da0073e9SAndroid Build Coastguard Worker // in C++17.
40*da0073e9SAndroid Build Coastguard Worker template <typename T>
41*da0073e9SAndroid Build Coastguard Worker using is_pod = std::conjunction<std::is_standard_layout<T>, std::is_trivial<T>>;
42*da0073e9SAndroid Build Coastguard Worker
43*da0073e9SAndroid Build Coastguard Worker template <typename T>
44*da0073e9SAndroid Build Coastguard Worker constexpr bool is_pod_v = is_pod<T>::value;
45*da0073e9SAndroid Build Coastguard Worker
46*da0073e9SAndroid Build Coastguard Worker namespace guts {
47*da0073e9SAndroid Build Coastguard Worker
48*da0073e9SAndroid Build Coastguard Worker template <typename Base, typename Child, typename... Args>
49*da0073e9SAndroid Build Coastguard Worker std::enable_if_t<
50*da0073e9SAndroid Build Coastguard Worker !std::is_array_v<Base> && !std::is_array_v<Child> &&
51*da0073e9SAndroid Build Coastguard Worker std::is_base_of_v<Base, Child>,
52*da0073e9SAndroid Build Coastguard Worker std::unique_ptr<Base>>
make_unique_base(Args &&...args)53*da0073e9SAndroid Build Coastguard Worker make_unique_base(Args&&... args) {
54*da0073e9SAndroid Build Coastguard Worker return std::unique_ptr<Base>(new Child(std::forward<Args>(args)...));
55*da0073e9SAndroid Build Coastguard Worker }
56*da0073e9SAndroid Build Coastguard Worker
57*da0073e9SAndroid Build Coastguard Worker #if defined(__cpp_lib_apply) && !defined(__CUDA_ARCH__) && !defined(__HIP__)
58*da0073e9SAndroid Build Coastguard Worker
59*da0073e9SAndroid Build Coastguard Worker template <class F, class Tuple>
decltype(auto)60*da0073e9SAndroid Build Coastguard Worker C10_HOST_DEVICE inline constexpr decltype(auto) apply(F&& f, Tuple&& t) {
61*da0073e9SAndroid Build Coastguard Worker return std::apply(std::forward<F>(f), std::forward<Tuple>(t));
62*da0073e9SAndroid Build Coastguard Worker }
63*da0073e9SAndroid Build Coastguard Worker
64*da0073e9SAndroid Build Coastguard Worker #else
65*da0073e9SAndroid Build Coastguard Worker
66*da0073e9SAndroid Build Coastguard Worker // Implementation from http://en.cppreference.com/w/cpp/utility/apply (but
67*da0073e9SAndroid Build Coastguard Worker // modified)
68*da0073e9SAndroid Build Coastguard Worker // TODO This is an incomplete implementation of std::apply, not working for
69*da0073e9SAndroid Build Coastguard Worker // member functions.
70*da0073e9SAndroid Build Coastguard Worker namespace detail {
71*da0073e9SAndroid Build Coastguard Worker template <class F, class Tuple, std::size_t... INDEX>
72*da0073e9SAndroid Build Coastguard Worker #if defined(_MSC_VER)
73*da0073e9SAndroid Build Coastguard Worker // MSVC has a problem with the decltype() return type, but it also doesn't need
74*da0073e9SAndroid Build Coastguard Worker // it
apply_impl(F && f,Tuple && t,std::index_sequence<INDEX...>)75*da0073e9SAndroid Build Coastguard Worker C10_HOST_DEVICE constexpr auto apply_impl(
76*da0073e9SAndroid Build Coastguard Worker F&& f,
77*da0073e9SAndroid Build Coastguard Worker Tuple&& t,
78*da0073e9SAndroid Build Coastguard Worker std::index_sequence<INDEX...>)
79*da0073e9SAndroid Build Coastguard Worker #else
80*da0073e9SAndroid Build Coastguard Worker // GCC/Clang need the decltype() return type
81*da0073e9SAndroid Build Coastguard Worker C10_HOST_DEVICE constexpr decltype(auto) apply_impl(
82*da0073e9SAndroid Build Coastguard Worker F&& f,
83*da0073e9SAndroid Build Coastguard Worker Tuple&& t,
84*da0073e9SAndroid Build Coastguard Worker std::index_sequence<INDEX...>)
85*da0073e9SAndroid Build Coastguard Worker #endif
86*da0073e9SAndroid Build Coastguard Worker {
87*da0073e9SAndroid Build Coastguard Worker return std::forward<F>(f)(std::get<INDEX>(std::forward<Tuple>(t))...);
88*da0073e9SAndroid Build Coastguard Worker }
89*da0073e9SAndroid Build Coastguard Worker } // namespace detail
90*da0073e9SAndroid Build Coastguard Worker
91*da0073e9SAndroid Build Coastguard Worker template <class F, class Tuple>
decltype(auto)92*da0073e9SAndroid Build Coastguard Worker C10_HOST_DEVICE constexpr decltype(auto) apply(F&& f, Tuple&& t) {
93*da0073e9SAndroid Build Coastguard Worker return detail::apply_impl(
94*da0073e9SAndroid Build Coastguard Worker std::forward<F>(f),
95*da0073e9SAndroid Build Coastguard Worker std::forward<Tuple>(t),
96*da0073e9SAndroid Build Coastguard Worker std::make_index_sequence<
97*da0073e9SAndroid Build Coastguard Worker std::tuple_size<std::remove_reference_t<Tuple>>::value>{});
98*da0073e9SAndroid Build Coastguard Worker }
99*da0073e9SAndroid Build Coastguard Worker
100*da0073e9SAndroid Build Coastguard Worker #endif
101*da0073e9SAndroid Build Coastguard Worker
102*da0073e9SAndroid Build Coastguard Worker template <typename Functor, typename... Args>
103*da0073e9SAndroid Build Coastguard Worker std::enable_if_t<
104*da0073e9SAndroid Build Coastguard Worker std::is_member_pointer_v<std::decay_t<Functor>>,
105*da0073e9SAndroid Build Coastguard Worker typename std::invoke_result_t<Functor, Args...>>
invoke(Functor && f,Args &&...args)106*da0073e9SAndroid Build Coastguard Worker invoke(Functor&& f, Args&&... args) {
107*da0073e9SAndroid Build Coastguard Worker return std::mem_fn(std::forward<Functor>(f))(std::forward<Args>(args)...);
108*da0073e9SAndroid Build Coastguard Worker }
109*da0073e9SAndroid Build Coastguard Worker
110*da0073e9SAndroid Build Coastguard Worker template <typename Functor, typename... Args>
111*da0073e9SAndroid Build Coastguard Worker std::enable_if_t<
112*da0073e9SAndroid Build Coastguard Worker !std::is_member_pointer_v<std::decay_t<Functor>>,
113*da0073e9SAndroid Build Coastguard Worker typename std::invoke_result_t<Functor, Args...>>
invoke(Functor && f,Args &&...args)114*da0073e9SAndroid Build Coastguard Worker invoke(Functor&& f, Args&&... args) {
115*da0073e9SAndroid Build Coastguard Worker return std::forward<Functor>(f)(std::forward<Args>(args)...);
116*da0073e9SAndroid Build Coastguard Worker }
117*da0073e9SAndroid Build Coastguard Worker
118*da0073e9SAndroid Build Coastguard Worker namespace detail {
119*da0073e9SAndroid Build Coastguard Worker struct _identity final {
120*da0073e9SAndroid Build Coastguard Worker template <class T>
121*da0073e9SAndroid Build Coastguard Worker using type_identity = T;
122*da0073e9SAndroid Build Coastguard Worker
123*da0073e9SAndroid Build Coastguard Worker template <class T>
decltypefinal124*da0073e9SAndroid Build Coastguard Worker decltype(auto) operator()(T&& arg) {
125*da0073e9SAndroid Build Coastguard Worker return std::forward<T>(arg);
126*da0073e9SAndroid Build Coastguard Worker }
127*da0073e9SAndroid Build Coastguard Worker };
128*da0073e9SAndroid Build Coastguard Worker
129*da0073e9SAndroid Build Coastguard Worker template <class Func, class Enable = void>
130*da0073e9SAndroid Build Coastguard Worker struct function_takes_identity_argument : std::false_type {};
131*da0073e9SAndroid Build Coastguard Worker
132*da0073e9SAndroid Build Coastguard Worker template <class Func>
133*da0073e9SAndroid Build Coastguard Worker struct function_takes_identity_argument<
134*da0073e9SAndroid Build Coastguard Worker Func,
135*da0073e9SAndroid Build Coastguard Worker std::void_t<decltype(std::declval<Func>()(_identity()))>> : std::true_type {
136*da0073e9SAndroid Build Coastguard Worker };
137*da0073e9SAndroid Build Coastguard Worker } // namespace detail
138*da0073e9SAndroid Build Coastguard Worker
139*da0073e9SAndroid Build Coastguard Worker } // namespace guts
140*da0073e9SAndroid Build Coastguard Worker } // namespace c10
141*da0073e9SAndroid Build Coastguard Worker
142*da0073e9SAndroid Build Coastguard Worker #endif // C10_UTIL_CPP17_H_
143