descr.h 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. /*
  2. pybind11/detail/descr.h: Helper type for concatenating type signatures at compile time
  3. Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
  4. All rights reserved. Use of this source code is governed by a
  5. BSD-style license that can be found in the LICENSE file.
  6. */
  7. #pragma once
  8. #include "common.h"
  9. PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
  10. PYBIND11_NAMESPACE_BEGIN(detail)
  11. #if !defined(_MSC_VER)
  12. # define PYBIND11_DESCR_CONSTEXPR static constexpr
  13. #else
  14. # define PYBIND11_DESCR_CONSTEXPR const
  15. #endif
  16. /* Concatenate type signatures at compile time */
  17. template <size_t N, typename... Ts>
  18. struct descr {
  19. char text[N + 1]{'\0'};
  20. constexpr descr() = default;
  21. // NOLINTNEXTLINE(google-explicit-constructor)
  22. constexpr descr(char const (&s)[N + 1]) : descr(s, make_index_sequence<N>()) {}
  23. template <size_t... Is>
  24. constexpr descr(char const (&s)[N + 1], index_sequence<Is...>) : text{s[Is]..., '\0'} {}
  25. template <typename... Chars>
  26. // NOLINTNEXTLINE(google-explicit-constructor)
  27. constexpr descr(char c, Chars... cs) : text{c, static_cast<char>(cs)..., '\0'} {}
  28. static constexpr std::array<const std::type_info *, sizeof...(Ts) + 1> types() {
  29. return {{&typeid(Ts)..., nullptr}};
  30. }
  31. };
  32. template <size_t N1, size_t N2, typename... Ts1, typename... Ts2, size_t... Is1, size_t... Is2>
  33. constexpr descr<N1 + N2, Ts1..., Ts2...> plus_impl(const descr<N1, Ts1...> &a,
  34. const descr<N2, Ts2...> &b,
  35. index_sequence<Is1...>,
  36. index_sequence<Is2...>) {
  37. PYBIND11_WORKAROUND_INCORRECT_MSVC_C4100(b);
  38. return {a.text[Is1]..., b.text[Is2]...};
  39. }
  40. template <size_t N1, size_t N2, typename... Ts1, typename... Ts2>
  41. constexpr descr<N1 + N2, Ts1..., Ts2...> operator+(const descr<N1, Ts1...> &a,
  42. const descr<N2, Ts2...> &b) {
  43. return plus_impl(a, b, make_index_sequence<N1>(), make_index_sequence<N2>());
  44. }
  45. template <size_t N>
  46. constexpr descr<N - 1> const_name(char const (&text)[N]) {
  47. return descr<N - 1>(text);
  48. }
  49. constexpr descr<0> const_name(char const (&)[1]) { return {}; }
  50. template <size_t Rem, size_t... Digits>
  51. struct int_to_str : int_to_str<Rem / 10, Rem % 10, Digits...> {};
  52. template <size_t... Digits>
  53. struct int_to_str<0, Digits...> {
  54. // WARNING: This only works with C++17 or higher.
  55. static constexpr auto digits = descr<sizeof...(Digits)>(('0' + Digits)...);
  56. };
  57. // Ternary description (like std::conditional)
  58. template <bool B, size_t N1, size_t N2>
  59. constexpr enable_if_t<B, descr<N1 - 1>> const_name(char const (&text1)[N1], char const (&)[N2]) {
  60. return const_name(text1);
  61. }
  62. template <bool B, size_t N1, size_t N2>
  63. constexpr enable_if_t<!B, descr<N2 - 1>> const_name(char const (&)[N1], char const (&text2)[N2]) {
  64. return const_name(text2);
  65. }
  66. template <bool B, typename T1, typename T2>
  67. constexpr enable_if_t<B, T1> const_name(const T1 &d, const T2 &) {
  68. return d;
  69. }
  70. template <bool B, typename T1, typename T2>
  71. constexpr enable_if_t<!B, T2> const_name(const T1 &, const T2 &d) {
  72. return d;
  73. }
  74. template <size_t Size>
  75. auto constexpr const_name() -> remove_cv_t<decltype(int_to_str<Size / 10, Size % 10>::digits)> {
  76. return int_to_str<Size / 10, Size % 10>::digits;
  77. }
  78. template <typename Type>
  79. constexpr descr<1, Type> const_name() {
  80. return {'%'};
  81. }
  82. // If "_" is defined as a macro, py::detail::_ cannot be provided.
  83. // It is therefore best to use py::detail::const_name universally.
  84. // This block is for backward compatibility only.
  85. // (The const_name code is repeated to avoid introducing a "_" #define ourselves.)
  86. #ifndef _
  87. # define PYBIND11_DETAIL_UNDERSCORE_BACKWARD_COMPATIBILITY
  88. template <size_t N>
  89. constexpr descr<N - 1> _(char const (&text)[N]) {
  90. return const_name<N>(text);
  91. }
  92. template <bool B, size_t N1, size_t N2>
  93. constexpr enable_if_t<B, descr<N1 - 1>> _(char const (&text1)[N1], char const (&text2)[N2]) {
  94. return const_name<B, N1, N2>(text1, text2);
  95. }
  96. template <bool B, size_t N1, size_t N2>
  97. constexpr enable_if_t<!B, descr<N2 - 1>> _(char const (&text1)[N1], char const (&text2)[N2]) {
  98. return const_name<B, N1, N2>(text1, text2);
  99. }
  100. template <bool B, typename T1, typename T2>
  101. constexpr enable_if_t<B, T1> _(const T1 &d1, const T2 &d2) {
  102. return const_name<B, T1, T2>(d1, d2);
  103. }
  104. template <bool B, typename T1, typename T2>
  105. constexpr enable_if_t<!B, T2> _(const T1 &d1, const T2 &d2) {
  106. return const_name<B, T1, T2>(d1, d2);
  107. }
  108. template <size_t Size>
  109. auto constexpr _() -> remove_cv_t<decltype(int_to_str<Size / 10, Size % 10>::digits)> {
  110. return const_name<Size>();
  111. }
  112. template <typename Type>
  113. constexpr descr<1, Type> _() {
  114. return const_name<Type>();
  115. }
  116. #endif // #ifndef _
  117. constexpr descr<0> concat() { return {}; }
  118. template <size_t N, typename... Ts>
  119. constexpr descr<N, Ts...> concat(const descr<N, Ts...> &descr) {
  120. return descr;
  121. }
  122. template <size_t N, typename... Ts, typename... Args>
  123. constexpr auto concat(const descr<N, Ts...> &d, const Args &...args)
  124. -> decltype(std::declval<descr<N + 2, Ts...>>() + concat(args...)) {
  125. return d + const_name(", ") + concat(args...);
  126. }
  127. template <size_t N, typename... Ts>
  128. constexpr descr<N + 2, Ts...> type_descr(const descr<N, Ts...> &descr) {
  129. return const_name("{") + descr + const_name("}");
  130. }
  131. PYBIND11_NAMESPACE_END(detail)
  132. PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)