descr.h 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  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. NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
  10. 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];
  20. constexpr descr() : text{'\0'} { }
  21. constexpr descr(char const (&s)[N+1]) : descr(s, make_index_sequence<N>()) { }
  22. template <size_t... Is>
  23. constexpr descr(char const (&s)[N+1], index_sequence<Is...>) : text{s[Is]..., '\0'} { }
  24. template <typename... Chars>
  25. constexpr descr(char c, Chars... cs) : text{c, static_cast<char>(cs)..., '\0'} { }
  26. static constexpr std::array<const std::type_info *, sizeof...(Ts) + 1> types() {
  27. return {{&typeid(Ts)..., nullptr}};
  28. }
  29. };
  30. template <size_t N1, size_t N2, typename... Ts1, typename... Ts2, size_t... Is1, size_t... Is2>
  31. constexpr descr<N1 + N2, Ts1..., Ts2...> plus_impl(const descr<N1, Ts1...> &a, const descr<N2, Ts2...> &b,
  32. index_sequence<Is1...>, index_sequence<Is2...>) {
  33. return {a.text[Is1]..., b.text[Is2]...};
  34. }
  35. template <size_t N1, size_t N2, typename... Ts1, typename... Ts2>
  36. constexpr descr<N1 + N2, Ts1..., Ts2...> operator+(const descr<N1, Ts1...> &a, const descr<N2, Ts2...> &b) {
  37. return plus_impl(a, b, make_index_sequence<N1>(), make_index_sequence<N2>());
  38. }
  39. template <size_t N>
  40. constexpr descr<N - 1> _(char const(&text)[N]) { return descr<N - 1>(text); }
  41. constexpr descr<0> _(char const(&)[1]) { return {}; }
  42. template <size_t Rem, size_t... Digits> struct int_to_str : int_to_str<Rem/10, Rem%10, Digits...> { };
  43. template <size_t...Digits> struct int_to_str<0, Digits...> {
  44. static constexpr auto digits = descr<sizeof...(Digits)>(('0' + Digits)...);
  45. };
  46. // Ternary description (like std::conditional)
  47. template <bool B, size_t N1, size_t N2>
  48. constexpr enable_if_t<B, descr<N1 - 1>> _(char const(&text1)[N1], char const(&)[N2]) {
  49. return _(text1);
  50. }
  51. template <bool B, size_t N1, size_t N2>
  52. constexpr enable_if_t<!B, descr<N2 - 1>> _(char const(&)[N1], char const(&text2)[N2]) {
  53. return _(text2);
  54. }
  55. template <bool B, typename T1, typename T2>
  56. constexpr enable_if_t<B, T1> _(const T1 &d, const T2 &) { return d; }
  57. template <bool B, typename T1, typename T2>
  58. constexpr enable_if_t<!B, T2> _(const T1 &, const T2 &d) { return d; }
  59. template <size_t Size> auto constexpr _() -> decltype(int_to_str<Size / 10, Size % 10>::digits) {
  60. return int_to_str<Size / 10, Size % 10>::digits;
  61. }
  62. template <typename Type> constexpr descr<1, Type> _() { return {'%'}; }
  63. constexpr descr<0> concat() { return {}; }
  64. template <size_t N, typename... Ts>
  65. constexpr descr<N, Ts...> concat(const descr<N, Ts...> &descr) { return descr; }
  66. template <size_t N, typename... Ts, typename... Args>
  67. constexpr auto concat(const descr<N, Ts...> &d, const Args &...args)
  68. -> decltype(std::declval<descr<N + 2, Ts...>>() + concat(args...)) {
  69. return d + _(", ") + concat(args...);
  70. }
  71. template <size_t N, typename... Ts>
  72. constexpr descr<N + 2, Ts...> type_descr(const descr<N, Ts...> &descr) {
  73. return _("{") + descr + _("}");
  74. }
  75. NAMESPACE_END(detail)
  76. NAMESPACE_END(PYBIND11_NAMESPACE)