diff --git a/CMakeLists.txt b/CMakeLists.txt index 6becf22d89466..eb681b6462c24 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,9 +35,9 @@ string(FIND "${CMAKE_CXX_FLAGS}" "-std=c++" env_cxx_standard) if(env_cxx_standard GREATER -1) message( WARNING "C++ standard version definition detected in environment variable." - "PyTorch requires -std=c++14. Please remove -std=c++ settings in your environment.") + "PyTorch requires -std=c++17. Please remove -std=c++ settings in your environment.") endif() -set(CMAKE_CXX_STANDARD 14 CACHE STRING "The C++ standard whose features are requested to build this target.") +set(CMAKE_CXX_STANDARD 17 CACHE STRING "The C++ standard whose features are requested to build this target.") set(CMAKE_C_STANDARD 11 CACHE STRING "The C standard whose features are requested to build this target.") if(DEFINED GLIBCXX_USE_CXX11_ABI) @@ -891,7 +891,6 @@ if(NOT MSVC) append_cxx_flag_if_supported("-Wno-unused-private-field" CMAKE_CXX_FLAGS) append_cxx_flag_if_supported("-Wno-inconsistent-missing-override" CMAKE_CXX_FLAGS) append_cxx_flag_if_supported("-Wno-aligned-allocation-unavailable" CMAKE_CXX_FLAGS) - append_cxx_flag_if_supported("-Wno-c++14-extensions" CMAKE_CXX_FLAGS) append_cxx_flag_if_supported("-Wno-constexpr-not-const" CMAKE_CXX_FLAGS) append_cxx_flag_if_supported("-Wno-missing-braces" CMAKE_CXX_FLAGS) append_cxx_flag_if_supported("-Wunused-lambda-capture" CMAKE_CXX_FLAGS) @@ -993,7 +992,6 @@ if(APPLE) endif() append_cxx_flag_if_supported("-Wno-unused-private-field" CMAKE_CXX_FLAGS) append_cxx_flag_if_supported("-Wno-missing-braces" CMAKE_CXX_FLAGS) - append_cxx_flag_if_supported("-Wno-c++14-extensions" CMAKE_CXX_FLAGS) append_cxx_flag_if_supported("-Wno-constexpr-not-const" CMAKE_CXX_FLAGS) endif() diff --git a/aten/src/ATen/Dispatch.h b/aten/src/ATen/Dispatch.h index d2f5a244ad573..08d4832b33a2b 100644 --- a/aten/src/ATen/Dispatch.h +++ b/aten/src/ATen/Dispatch.h @@ -51,8 +51,6 @@ TORCH_API void record_kernel_function_dtype(std::string name); #define RECORD_KERNEL_FUNCTION_DTYPE(NAME, enum_type) #endif -// Avoid if_constexpr if possble, as it's more expensive to compile -#if defined __cpp_if_constexpr #define AT_PRIVATE_CHECK_SELECTIVE_BUILD(enum_type) \ do { \ if constexpr (!at::should_include_kernel_dtype( \ @@ -64,17 +62,6 @@ TORCH_API void record_kernel_function_dtype(std::string name); at_dispatch_name); \ } \ } while (0) -#else // defined __cpp_if_constexpr -#define AT_PRIVATE_CHECK_SELECTIVE_BUILD(enum_type) \ - at::guts::if_constexpr([&] { \ - AT_ERROR( \ - "dtype '", \ - toString(enum_type), \ - "' not selected for kernel tag ", \ - at_dispatch_name); \ - }) -#endif // Workaround for C10_UNUSED because CUDA 10.2 and below fails to handle unused // attribute in the type aliasing context. Keep name long and verbose to avoid diff --git a/aten/src/ATen/core/boxing/impl/boxing.h b/aten/src/ATen/core/boxing/impl/boxing.h index ccac9ebe8f61b..20ad7dbdba057 100644 --- a/aten/src/ATen/core/boxing/impl/boxing.h +++ b/aten/src/ATen/core/boxing/impl/boxing.h @@ -226,20 +226,17 @@ struct BoxedKernelWrapper< torch::jit::Stack stack = boxArgs(std::forward(args)...); boxed_kernel_func.callBoxed(opHandle, dispatchKeySet, &stack); - return guts::if_constexpr::value>( - [&] (auto delay_check) { - // op has pushed one or more values onto the stack. - return delay_check(PopResult::call(stack)); - }, - [&] { - // op returns void, boxed kernel has pushed nothing onto stack. - TORCH_INTERNAL_ASSERT_DEBUG_ONLY( - stack.size() == 0, - "Boxed kernel was expected to return no values on the stack, ", - "but instead returned ", stack.size(), " values." - ); - } - ); + if constexpr (!std::is_same_v) { + // op has pushed one or more values onto the stack. + return PopResult::call(stack); + } else { + // op returns void, boxed kernel has pushed nothing onto stack. + TORCH_INTERNAL_ASSERT_DEBUG_ONLY( + stack.size() == 0, + "Boxed kernel was expected to return no values on the stack, ", + "but instead returned ", stack.size(), " values." + ); + } } }; diff --git a/aten/src/ATen/core/boxing/impl/make_boxed_from_unboxed_functor.h b/aten/src/ATen/core/boxing/impl/make_boxed_from_unboxed_functor.h index 7f728dd0333bf..82032ff6ba17e 100644 --- a/aten/src/ATen/core/boxing/impl/make_boxed_from_unboxed_functor.h +++ b/aten/src/ATen/core/boxing/impl/make_boxed_from_unboxed_functor.h @@ -103,12 +103,12 @@ namespace impl { template struct assert_is_valid_input_type { assert_is_valid_input_type() { - guts::if_constexpr::value>([] { + if constexpr (guts::typelist::contains::value) { /* everything is ok, this is a primitive type */ - }, /* else */ [] { + } else { /* otherwise this must be an instance of a valid custom class, since it can only have been created via IValue(x), which ensures this. */ - }); + }; } }; @@ -209,12 +209,12 @@ namespace impl { template struct assert_is_valid_output_type { assert_is_valid_output_type() { - guts::if_constexpr::value>([] { + if constexpr (guts::typelist::contains::value) { /* everything is ok, this is a primitive type */ - }, /* else */ [] { + } else { /* otherwise T is verified to be a registered custom class in the IValue constructor, so no benefit in double-checking here */ - }); + } } }; @@ -556,34 +556,17 @@ namespace impl { using ArgTypes = typename c10::remove_DispatchKeySet_arg_from_func::parameter_types; constexpr bool has_outputs = !std::is_same::value; constexpr size_t num_inputs = guts::typelist::size::value; -#ifdef __cpp_if_constexpr if constexpr (has_outputs) { -#else - guts::if_constexpr([&] (auto delay_check) { -#endif // Decay ReturnType to ReturnType_ so that if a reference gets returned, we actually store it by value // and don't get a dangling reference. This is only required because some kernels still return `Tensor&`. -#ifdef __cpp_if_constexpr using ReturnType_ = std::decay_t; ReturnType_ output = call_functor_with_args_from_stack(functor, dispatchKeySet, stack); -#else - using ReturnType_ = std::decay_t>; - ReturnType_ output = call_functor_with_args_from_stack(functor, dispatchKeySet, delay_check(stack)); -#endif torch::jit::drop(*stack, num_inputs); push_outputs::call(std::move(output), stack); -#ifdef __cpp_if_constexpr } else { -#else - }, /* else */ [&] { -#endif call_functor_with_args_from_stack(functor, dispatchKeySet, stack); torch::jit::drop(*stack, num_inputs); -#ifdef __cpp_if_constexpr } -#else - }); -#endif } }; } // namespace impl diff --git a/aten/src/ATen/core/ivalue_inl.h b/aten/src/ATen/core/ivalue_inl.h index 9bef63d8b2c54..c8e7b47bc9332 100644 --- a/aten/src/ATen/core/ivalue_inl.h +++ b/aten/src/ATen/core/ivalue_inl.h @@ -975,11 +975,9 @@ struct C10_EXPORT ivalue::Future final : c10::intrusive_ptr_target { */ template void addCallback(T callback) { -#if __cpp_lib_is_invocable >= 201703 static_assert( std::is_invocable_r::value, "The callback must have signature void(Future&)"); -#endif std::unique_lock lock(mutex_); if (completed()) { lock.unlock(); @@ -997,30 +995,26 @@ struct C10_EXPORT ivalue::Future final : c10::intrusive_ptr_target { template c10::intrusive_ptr then(T callback, TypePtr type) { using IValueWithStorages = std::tuple>; -#if __cpp_lib_is_invocable >= 201703 static_assert( guts::disjunction< std::is_invocable_r, std::is_invocable_r>::value, "The callback must have signature IValue(Future&) or " "std::tuple>(Future&)"); -#endif auto childFut = createInstance(std::move(type)); addCallback([childFut, cb = std::move(callback)](Future& parentFut) mutable { try { - guts::if_constexpr, - IValueWithStorages>::value>( - [&](auto identity) { + IValueWithStorages>) { IValue value; std::vector storages; - std::tie(value, storages) = identity(cb)(parentFut); + std::tie(value, storages) = cb(parentFut); childFut->markCompleted(std::move(value), std::move(storages)); - }, - [&](auto identity) { - childFut->markCompleted(identity(cb)(parentFut)); - }); + } else { + childFut->markCompleted(cb(parentFut)); + }; } catch (std::exception&) { childFut->setError(std::current_exception()); } @@ -1030,11 +1024,9 @@ struct C10_EXPORT ivalue::Future final : c10::intrusive_ptr_target { template c10::intrusive_ptr thenAsync(T callback, TypePtr type) { -#if __cpp_lib_is_invocable >= 201703 static_assert( std::is_invocable_r, T, Future&>::value, "The callback must have signature c10::intrusive_ptr(Future&)"); -#endif auto childFut = createInstance(std::move(type)); addCallback( [childFut, cb = std::move(callback)](Future& parentFut) mutable { @@ -1111,11 +1103,9 @@ struct C10_EXPORT ivalue::Future final : c10::intrusive_ptr_target { // synchronize them with the value, and so on (if needed). template void invokeCallback(T callback) { -#if __cpp_lib_is_invocable >= 201703 static_assert( std::is_invocable_r::value, "The callback must have signature void(Future&)"); -#endif c10::OptionalDeviceGuard deviceGuard(currentDevice_); diff --git a/aten/src/ATen/native/ReduceOps.cpp b/aten/src/ATen/native/ReduceOps.cpp index 97aeb44951d04..84dda014efca8 100644 --- a/aten/src/ATen/native/ReduceOps.cpp +++ b/aten/src/ATen/native/ReduceOps.cpp @@ -1155,11 +1155,11 @@ Tensor trace_cpu(const Tensor& self) { sum += t_data[i * (t_stride_0 + t_stride_1)]; } - c10::guts::if_constexpr::value>( - // all integer types get promoted to kLong - [&] (auto _) { *result.data_ptr() = _(sum); }, // then-case, invalid for non-integral types - [&] (auto _) { *result.data_ptr() = _(sum); } // else-case, invalid for integral types - ); + if constexpr (std::is_integral_v) { + *result.data_ptr() = sum; + } else { + *result.data_ptr() = sum; + } }); return result; diff --git a/aten/src/ATen/native/cuda/jit_utils.cpp b/aten/src/ATen/native/cuda/jit_utils.cpp index f86b624b84f7c..df84b61166c78 100644 --- a/aten/src/ATen/native/cuda/jit_utils.cpp +++ b/aten/src/ATen/native/cuda/jit_utils.cpp @@ -1531,7 +1531,7 @@ NvrtcFunction jit_pwise_function( &program, code.c_str(), nullptr, 0, nullptr, nullptr)); #ifdef USE_ROCM - std::vector args = {"--std=c++14"}; + std::vector args = {"--std=c++17"}; #else // Constructs nvrtc build arguments // CUDA 11.1 allows going directly to SASS (sm_) instead of PTX (compute_) @@ -1546,7 +1546,7 @@ NvrtcFunction jit_pwise_function( std::to_string(cuda_minor); // NOLINTNEXTLINE(cppcoreguidelines-init-variables) std::vector args = { - "--std=c++14", compute.c_str(), "-default-device"}; + "--std=c++17", compute.c_str(), "-default-device"}; #endif #ifndef NDEBUG diff --git a/c10/CMakeLists.txt b/c10/CMakeLists.txt index 5f1b9777a1205..00a71352e3739 100644 --- a/c10/CMakeLists.txt +++ b/c10/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.10 FATAL_ERROR) project(c10 CXX) -set(CMAKE_CXX_STANDARD 14 CACHE STRING "The C++ standard whose features are requested to build this target.") +set(CMAKE_CXX_STANDARD 17 CACHE STRING "The C++ standard whose features are requested to build this target.") set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # Main build file for the C10 library. diff --git a/c10/util/C++17.h b/c10/util/C++17.h index c51275721e584..f374b86aa31f9 100644 --- a/c10/util/C++17.h +++ b/c10/util/C++17.h @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -22,9 +23,9 @@ "You're trying to build PyTorch with a too old version of Clang. We need Clang 4 or later." #endif -#if (defined(_MSC_VER) && (!defined(_MSVC_LANG) || _MSVC_LANG < 201402L)) || \ - (!defined(_MSC_VER) && __cplusplus < 201402L) -#error You need C++14 to compile PyTorch +#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)) @@ -37,14 +38,8 @@ namespace c10 { -// in c++17 std::result_of has been superceded by std::invoke_result. Since -// c++20, std::result_of is removed. template -#if defined(__cpp_lib_is_invocable) && __cpp_lib_is_invocable >= 201703L using invoke_result = typename std::invoke_result; -#else -using invoke_result = typename std::result_of; -#endif template using invoke_result_t = typename invoke_result::type; @@ -60,8 +55,6 @@ make_unique_base(Args&&... args) { return std::unique_ptr(new Child(std::forward(args)...)); } -#if defined(__cpp_lib_logical_traits) && !(defined(_MSC_VER) && _MSC_VER < 1920) - template using conjunction = std::conjunction; template @@ -71,55 +64,9 @@ using bool_constant = std::bool_constant; template using negation = std::negation; -#else - -// Implementation taken from http://en.cppreference.com/w/cpp/types/conjunction -template -struct conjunction : std::true_type {}; -template -struct conjunction : B1 {}; -template -struct conjunction - : std::conditional_t, B1> {}; - -// Implementation taken from http://en.cppreference.com/w/cpp/types/disjunction -template -struct disjunction : std::false_type {}; -template -struct disjunction : B1 {}; -template -struct disjunction - : std::conditional_t> {}; - -// Implementation taken from -// http://en.cppreference.com/w/cpp/types/integral_constant -template -using bool_constant = std::integral_constant; - -// Implementation taken from http://en.cppreference.com/w/cpp/types/negation -template -struct negation : bool_constant {}; - -#endif - -#ifdef __cpp_lib_void_t - template using void_t = std::void_t; -#else - -// Implementation taken from http://en.cppreference.com/w/cpp/types/void_t -// (it takes CWG1558 into account and also works for older compilers) -template -struct make_void { - typedef void type; -}; -template -using void_t = typename make_void::type; - -#endif - #if defined(USE_ROCM) // rocm doesn't like the C10_HOST_DEVICE #define CUDA_HOST_DEVICE @@ -127,51 +74,11 @@ using void_t = typename make_void::type; #define CUDA_HOST_DEVICE C10_HOST_DEVICE #endif -#ifdef __cpp_lib_apply - template CUDA_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 -CUDA_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 -CUDA_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 - #undef CUDA_HOST_DEVICE template @@ -219,68 +126,6 @@ struct function_takes_identity_argument< void_t()(_identity()))>> : std::true_type {}; #endif -template -struct _if_constexpr; - -template <> -struct _if_constexpr final { - template < - class ThenCallback, - class ElseCallback, - std::enable_if_t< - function_takes_identity_argument::value, - void*> = nullptr> - static decltype(auto) call( - ThenCallback&& thenCallback, - ElseCallback&& /* elseCallback */) { - // The _identity instance passed in can be used to delay evaluation of an - // expression, because the compiler can't know that it's just the identity - // we're passing in. - return thenCallback(_identity()); - } - - template < - class ThenCallback, - class ElseCallback, - std::enable_if_t< - !function_takes_identity_argument::value, - void*> = nullptr> - static decltype(auto) call( - ThenCallback&& thenCallback, - ElseCallback&& /* elseCallback */) { - return thenCallback(); - } -}; - -template <> -struct _if_constexpr final { - template < - class ThenCallback, - class ElseCallback, - std::enable_if_t< - function_takes_identity_argument::value, - void*> = nullptr> - static decltype(auto) call( - ThenCallback&& /* thenCallback */, - ElseCallback&& elseCallback) { - // The _identity instance passed in can be used to delay evaluation of an - // expression, because the compiler can't know that it's just the identity - // we're passing in. - return elseCallback(_identity()); - } - - template < - class ThenCallback, - class ElseCallback, - std::enable_if_t< - !function_takes_identity_argument::value, - void*> = nullptr> - static decltype(auto) call( - ThenCallback&& /* thenCallback */, - ElseCallback&& elseCallback) { - return elseCallback(); - } -}; } // namespace detail /* @@ -341,7 +186,6 @@ template decltype(auto) if_constexpr( ThenCallback&& thenCallback, ElseCallback&& elseCallback) { -#if defined(__cpp_if_constexpr) // If we have C++17, just use it's "if constexpr" feature instead of wrapping // it. This will give us better error messages. if constexpr (Condition) { @@ -363,17 +207,10 @@ decltype(auto) if_constexpr( return static_cast(elseCallback)(); } } -#else - // C++14 implementation of if constexpr - return detail::_if_constexpr::call( - static_cast(thenCallback), - static_cast(elseCallback)); -#endif } template decltype(auto) if_constexpr(ThenCallback&& thenCallback) { -#if defined(__cpp_if_constexpr) // If we have C++17, just use it's "if constexpr" feature instead of wrapping // it. This will give us better error messages. if constexpr (Condition) { @@ -388,11 +225,6 @@ decltype(auto) if_constexpr(ThenCallback&& thenCallback) { return static_cast(thenCallback)(); } } -#else - // C++14 implementation of if constexpr - return if_constexpr( - static_cast(thenCallback), [](auto) {}); -#endif } // GCC 4.8 doesn't define std::to_string, even though that's in C++11. Let's diff --git a/cmake/Dependencies.cmake b/cmake/Dependencies.cmake index 49b7fd5025b43..0d11bda847208 100644 --- a/cmake/Dependencies.cmake +++ b/cmake/Dependencies.cmake @@ -1658,7 +1658,7 @@ if(NOT INTERN_BUILD_MOBILE) string(APPEND CMAKE_CUDA_FLAGS " -Wno-deprecated-gpu-targets --expt-extended-lambda") if(NOT CMAKE_CXX_COMPILER_ID STREQUAL "GNU") - set(CMAKE_CXX_STANDARD 14 CACHE STRING "The C++ standard whose features are requested to build this target.") + set(CMAKE_CXX_STANDARD 17 CACHE STRING "The C++ standard whose features are requested to build this target.") endif() # use cub in a safe manner, see: diff --git a/cmake/public/utils.cmake b/cmake/public/utils.cmake index 5944a5a1a6269..9ad0a2f96f88f 100644 --- a/cmake/public/utils.cmake +++ b/cmake/public/utils.cmake @@ -407,7 +407,7 @@ endmacro() # Usage: # torch_compile_options(lib_name) function(torch_compile_options libname) - set_property(TARGET ${libname} PROPERTY CXX_STANDARD 14) + set_property(TARGET ${libname} PROPERTY CXX_STANDARD 17) set(private_compile_options "") # ---[ Check if warnings should be errors.