descr.h 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. #if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
  2. /*
  3. pybind11/detail/descr.h: Helper type for concatenating type signatures at compile time
  4. Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
  5. All rights reserved. Use of this source code is governed by a
  6. BSD-style license that can be found in the LICENSE file.
  7. */
  8. #pragma once
  9. #include "common.h"
  10. PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
  11. PYBIND11_NAMESPACE_BEGIN(detail)
  12. #if !defined(_MSC_VER)
  13. # define PYBIND11_DESCR_CONSTEXPR static constexpr
  14. #else
  15. # define PYBIND11_DESCR_CONSTEXPR const
  16. #endif
  17. /* Concatenate type signatures at compile time */
  18. template <size_t N, typename... Ts>
  19. struct descr {
  20. char text[N + 1]{'\0'};
  21. constexpr descr() = default;
  22. // NOLINTNEXTLINE(google-explicit-constructor)
  23. constexpr descr(char const (&s)[N + 1]) : descr(s, make_index_sequence<N>()) {}
  24. template <size_t... Is>
  25. constexpr descr(char const (&s)[N + 1], index_sequence<Is...>) : text{s[Is]..., '\0'} {}
  26. template <typename... Chars>
  27. // NOLINTNEXTLINE(google-explicit-constructor)
  28. constexpr descr(char c, Chars... cs) : text{c, static_cast<char>(cs)..., '\0'} {}
  29. static constexpr std::array<const std::type_info *, sizeof...(Ts) + 1> types() {
  30. return {{&typeid(Ts)..., nullptr}};
  31. }
  32. };
  33. template <size_t N1, size_t N2, typename... Ts1, typename... Ts2, size_t... Is1, size_t... Is2>
  34. constexpr descr<N1 + N2, Ts1..., Ts2...> plus_impl(const descr<N1, Ts1...> &a,
  35. const descr<N2, Ts2...> &b,
  36. index_sequence<Is1...>,
  37. index_sequence<Is2...>) {
  38. PYBIND11_WORKAROUND_INCORRECT_MSVC_C4100(b);
  39. return {a.text[Is1]..., b.text[Is2]...};
  40. }
  41. template <size_t N1, size_t N2, typename... Ts1, typename... Ts2>
  42. constexpr descr<N1 + N2, Ts1..., Ts2...> operator+(const descr<N1, Ts1...> &a,
  43. const descr<N2, Ts2...> &b) {
  44. return plus_impl(a, b, make_index_sequence<N1>(), make_index_sequence<N2>());
  45. }
  46. template <size_t N>
  47. constexpr descr<N - 1> const_name(char const (&text)[N]) {
  48. return descr<N - 1>(text);
  49. }
  50. constexpr descr<0> const_name(char const (&)[1]) { return {}; }
  51. template <size_t Rem, size_t... Digits>
  52. struct int_to_str : int_to_str<Rem / 10, Rem % 10, Digits...> {};
  53. template <size_t... Digits>
  54. struct int_to_str<0, Digits...> {
  55. // WARNING: This only works with C++17 or higher.
  56. static constexpr auto digits = descr<sizeof...(Digits)>(('0' + Digits)...);
  57. };
  58. // Ternary description (like std::conditional)
  59. template <bool B, size_t N1, size_t N2>
  60. constexpr enable_if_t<B, descr<N1 - 1>> const_name(char const (&text1)[N1], char const (&)[N2]) {
  61. return const_name(text1);
  62. }
  63. template <bool B, size_t N1, size_t N2>
  64. constexpr enable_if_t<!B, descr<N2 - 1>> const_name(char const (&)[N1], char const (&text2)[N2]) {
  65. return const_name(text2);
  66. }
  67. template <bool B, typename T1, typename T2>
  68. constexpr enable_if_t<B, T1> const_name(const T1 &d, const T2 &) {
  69. return d;
  70. }
  71. template <bool B, typename T1, typename T2>
  72. constexpr enable_if_t<!B, T2> const_name(const T1 &, const T2 &d) {
  73. return d;
  74. }
  75. template <size_t Size>
  76. auto constexpr const_name() -> remove_cv_t<decltype(int_to_str<Size / 10, Size % 10>::digits)> {
  77. return int_to_str<Size / 10, Size % 10>::digits;
  78. }
  79. template <typename Type>
  80. constexpr descr<1, Type> const_name() {
  81. return {'%'};
  82. }
  83. // Use a different name based on whether the parameter is used as input or output
  84. template <size_t N1, size_t N2>
  85. constexpr descr<N1 + N2 + 1> io_name(char const (&text1)[N1], char const (&text2)[N2]) {
  86. return const_name("@") + const_name(text1) + const_name("@") + const_name(text2)
  87. + const_name("@");
  88. }
  89. // Ternary description for io_name (like the numeric type_caster)
  90. template <bool B, size_t N1, size_t N2, size_t N3, size_t N4>
  91. constexpr enable_if_t<B, descr<N1 + N2 + 1>>
  92. io_name(char const (&text1)[N1], char const (&text2)[N2], char const (&)[N3], char const (&)[N4]) {
  93. return io_name(text1, text2);
  94. }
  95. template <bool B, size_t N1, size_t N2, size_t N3, size_t N4>
  96. constexpr enable_if_t<!B, descr<N3 + N4 + 1>>
  97. io_name(char const (&)[N1], char const (&)[N2], char const (&text3)[N3], char const (&text4)[N4]) {
  98. return io_name(text3, text4);
  99. }
  100. // If "_" is defined as a macro, py::detail::_ cannot be provided.
  101. // It is therefore best to use py::detail::const_name universally.
  102. // This block is for backward compatibility only.
  103. // (The const_name code is repeated to avoid introducing a "_" #define ourselves.)
  104. #ifndef _
  105. # define PYBIND11_DETAIL_UNDERSCORE_BACKWARD_COMPATIBILITY
  106. template <size_t N>
  107. constexpr descr<N - 1> _(char const (&text)[N]) {
  108. return const_name<N>(text);
  109. }
  110. template <bool B, size_t N1, size_t N2>
  111. constexpr enable_if_t<B, descr<N1 - 1>> _(char const (&text1)[N1], char const (&text2)[N2]) {
  112. return const_name<B, N1, N2>(text1, text2);
  113. }
  114. template <bool B, size_t N1, size_t N2>
  115. constexpr enable_if_t<!B, descr<N2 - 1>> _(char const (&text1)[N1], char const (&text2)[N2]) {
  116. return const_name<B, N1, N2>(text1, text2);
  117. }
  118. template <bool B, typename T1, typename T2>
  119. constexpr enable_if_t<B, T1> _(const T1 &d1, const T2 &d2) {
  120. return const_name<B, T1, T2>(d1, d2);
  121. }
  122. template <bool B, typename T1, typename T2>
  123. constexpr enable_if_t<!B, T2> _(const T1 &d1, const T2 &d2) {
  124. return const_name<B, T1, T2>(d1, d2);
  125. }
  126. template <size_t Size>
  127. auto constexpr _() -> remove_cv_t<decltype(int_to_str<Size / 10, Size % 10>::digits)> {
  128. return const_name<Size>();
  129. }
  130. template <typename Type>
  131. constexpr descr<1, Type> _() {
  132. return const_name<Type>();
  133. }
  134. #endif // #ifndef _
  135. constexpr descr<0> concat() { return {}; }
  136. constexpr descr<0> union_concat() { return {}; }
  137. template <size_t N, typename... Ts>
  138. constexpr descr<N, Ts...> concat(const descr<N, Ts...> &descr) {
  139. return descr;
  140. }
  141. template <size_t N, typename... Ts>
  142. constexpr descr<N, Ts...> union_concat(const descr<N, Ts...> &descr) {
  143. return descr;
  144. }
  145. template <size_t N1, size_t N2, typename... Ts1, typename... Ts2>
  146. constexpr descr<N1 + N2 + 3, Ts1..., Ts2...> operator|(const descr<N1, Ts1...> &a,
  147. const descr<N2, Ts2...> &b) {
  148. return a + const_name(" | ") + b;
  149. }
  150. #ifdef __cpp_fold_expressions
  151. template <size_t N1, size_t N2, typename... Ts1, typename... Ts2>
  152. constexpr descr<N1 + N2 + 2, Ts1..., Ts2...> operator,(const descr<N1, Ts1...> &a,
  153. const descr<N2, Ts2...> &b) {
  154. return a + const_name(", ") + b;
  155. }
  156. template <size_t N, typename... Ts, typename... Args>
  157. constexpr auto concat(const descr<N, Ts...> &d, const Args &...args) {
  158. return (d, ..., args);
  159. }
  160. template <size_t N, typename... Ts, typename... Args>
  161. constexpr auto union_concat(const descr<N, Ts...> &d, const Args &...args) {
  162. return (d | ... | args);
  163. }
  164. #else
  165. template <size_t N, typename... Ts, typename... Args>
  166. constexpr auto concat(const descr<N, Ts...> &d, const Args &...args)
  167. -> decltype(std::declval<descr<N + 2, Ts...>>() + concat(args...)) {
  168. return d + const_name(", ") + concat(args...);
  169. }
  170. template <size_t N, typename... Ts, typename... Args>
  171. constexpr auto union_concat(const descr<N, Ts...> &d, const Args &...args)
  172. -> decltype(std::declval<descr<N + 3, Ts...>>() + union_concat(args...)) {
  173. return d + const_name(" | ") + union_concat(args...);
  174. }
  175. #endif
  176. template <size_t N, typename... Ts>
  177. constexpr descr<N + 2, Ts...> type_descr(const descr<N, Ts...> &descr) {
  178. return const_name("{") + descr + const_name("}");
  179. }
  180. template <size_t N, typename... Ts>
  181. constexpr descr<N + 4, Ts...> arg_descr(const descr<N, Ts...> &descr) {
  182. return const_name("@^") + descr + const_name("@!");
  183. }
  184. template <size_t N, typename... Ts>
  185. constexpr descr<N + 4, Ts...> return_descr(const descr<N, Ts...> &descr) {
  186. return const_name("@$") + descr + const_name("@!");
  187. }
  188. PYBIND11_NAMESPACE_END(detail)
  189. PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)
  190. #else
  191. #error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
  192. #endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)