LCOV - code coverage report
Current view: top level - libtorch/include/c10/util - C++17.h (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 4 0
Test Date: 2024-04-30 13:17:26 Functions: 0.0 % 2 0

            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