|
14 | 14 | NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
|
15 | 15 | NAMESPACE_BEGIN(detail)
|
16 | 16 |
|
| 17 | +#if !defined(_MSC_VER) |
| 18 | +# define PYBIND11_DESCR_CONSTEXPR static constexpr |
| 19 | +#else |
| 20 | +# define PYBIND11_DESCR_CONSTEXPR const |
| 21 | +#endif |
| 22 | + |
17 | 23 | /* Concatenate type signatures at compile time */
|
18 |
| -template <size_t Size1, size_t Size2> class descr { |
19 |
| - template <size_t Size1_, size_t Size2_> friend class descr; |
20 |
| -public: |
21 |
| - constexpr descr() = default; |
22 |
| - |
23 |
| - constexpr descr(char const (&text) [Size1+1], const std::type_info * const (&types)[Size2+1]) |
24 |
| - : descr(text, types, |
25 |
| - make_index_sequence<Size1>(), |
26 |
| - make_index_sequence<Size2>()) { } |
27 |
| - |
28 |
| - constexpr const char *text() const { return m_text; } |
29 |
| - constexpr const std::type_info * const * types() const { return m_types; } |
30 |
| - |
31 |
| - template <size_t OtherSize1, size_t OtherSize2> |
32 |
| - constexpr descr<Size1 + OtherSize1, Size2 + OtherSize2> operator+(const descr<OtherSize1, OtherSize2> &other) const { |
33 |
| - return concat(other, |
34 |
| - make_index_sequence<Size1>(), |
35 |
| - make_index_sequence<Size2>(), |
36 |
| - make_index_sequence<OtherSize1>(), |
37 |
| - make_index_sequence<OtherSize2>()); |
38 |
| - } |
| 24 | +template <size_t N, typename... Ts> |
| 25 | +struct descr { |
| 26 | + char text[N + 1]; |
39 | 27 |
|
40 |
| -protected: |
41 |
| - template <size_t... Indices1, size_t... Indices2> |
42 |
| - constexpr descr( |
43 |
| - char const (&text) [Size1+1], |
44 |
| - const std::type_info * const (&types) [Size2+1], |
45 |
| - index_sequence<Indices1...>, index_sequence<Indices2...>) |
46 |
| - : m_text{text[Indices1]..., '\0'}, |
47 |
| - m_types{types[Indices2]..., nullptr } {} |
48 |
| - |
49 |
| - template <size_t OtherSize1, size_t OtherSize2, size_t... Indices1, |
50 |
| - size_t... Indices2, size_t... OtherIndices1, size_t... OtherIndices2> |
51 |
| - constexpr descr<Size1 + OtherSize1, Size2 + OtherSize2> |
52 |
| - concat(const descr<OtherSize1, OtherSize2> &other, |
53 |
| - index_sequence<Indices1...>, index_sequence<Indices2...>, |
54 |
| - index_sequence<OtherIndices1...>, index_sequence<OtherIndices2...>) const { |
55 |
| - return descr<Size1 + OtherSize1, Size2 + OtherSize2>( |
56 |
| - { m_text[Indices1]..., other.m_text[OtherIndices1]..., '\0' }, |
57 |
| - { m_types[Indices2]..., other.m_types[OtherIndices2]..., nullptr } |
58 |
| - ); |
59 |
| - } |
| 28 | + constexpr descr() : text{'\0'} { } |
| 29 | + constexpr descr(char const (&s)[N+1]) : descr(s, make_index_sequence<N>()) { } |
60 | 30 |
|
61 |
| -protected: |
62 |
| - char m_text[Size1 + 1]; |
63 |
| - const std::type_info * m_types[Size2 + 1]; |
| 31 | + template <size_t... Is> |
| 32 | + constexpr descr(char const (&s)[N+1], index_sequence<Is...>) : text{s[Is]..., '\0'} { } |
| 33 | + |
| 34 | + template <typename... Chars> |
| 35 | + constexpr descr(char c, Chars... cs) : text{c, static_cast<char>(cs)..., '\0'} { } |
| 36 | + |
| 37 | + static constexpr std::array<const std::type_info *, sizeof...(Ts) + 1> types() { |
| 38 | + return {{&typeid(Ts)..., nullptr}}; |
| 39 | + } |
64 | 40 | };
|
65 | 41 |
|
66 |
| -template <size_t Size> constexpr descr<Size - 1, 0> _(char const(&text)[Size]) { |
67 |
| - return descr<Size - 1, 0>(text, { nullptr }); |
| 42 | +template <size_t N1, size_t N2, typename... Ts1, typename... Ts2, size_t... Is1, size_t... Is2> |
| 43 | +constexpr descr<N1 + N2, Ts1..., Ts2...> plus_impl(const descr<N1, Ts1...> &a, const descr<N2, Ts2...> &b, |
| 44 | + index_sequence<Is1...>, index_sequence<Is2...>) { |
| 45 | + return {a.text[Is1]..., b.text[Is2]...}; |
68 | 46 | }
|
69 | 47 |
|
| 48 | +template <size_t N1, size_t N2, typename... Ts1, typename... Ts2> |
| 49 | +constexpr descr<N1 + N2, Ts1..., Ts2...> operator+(const descr<N1, Ts1...> &a, const descr<N2, Ts2...> &b) { |
| 50 | + return plus_impl(a, b, make_index_sequence<N1>(), make_index_sequence<N2>()); |
| 51 | +} |
| 52 | + |
| 53 | +template <size_t N> |
| 54 | +constexpr descr<N - 1> _(char const(&text)[N]) { return descr<N - 1>(text); } |
| 55 | +constexpr descr<0> _(char const(&)[1]) { return {}; } |
| 56 | + |
70 | 57 | template <size_t Rem, size_t... Digits> struct int_to_str : int_to_str<Rem/10, Rem%10, Digits...> { };
|
71 | 58 | template <size_t...Digits> struct int_to_str<0, Digits...> {
|
72 |
| - static constexpr auto digits = descr<sizeof...(Digits), 0>({ ('0' + Digits)..., '\0' }, { nullptr }); |
| 59 | + static constexpr auto digits = descr<sizeof...(Digits)>(('0' + Digits)...); |
73 | 60 | };
|
74 | 61 |
|
75 | 62 | // Ternary description (like std::conditional)
|
76 |
| -template <bool B, size_t Size1, size_t Size2> |
77 |
| -constexpr enable_if_t<B, descr<Size1 - 1, 0>> _(char const(&text1)[Size1], char const(&)[Size2]) { |
| 63 | +template <bool B, size_t N1, size_t N2> |
| 64 | +constexpr enable_if_t<B, descr<N1 - 1>> _(char const(&text1)[N1], char const(&)[N2]) { |
78 | 65 | return _(text1);
|
79 | 66 | }
|
80 |
| -template <bool B, size_t Size1, size_t Size2> |
81 |
| -constexpr enable_if_t<!B, descr<Size2 - 1, 0>> _(char const(&)[Size1], char const(&text2)[Size2]) { |
| 67 | +template <bool B, size_t N1, size_t N2> |
| 68 | +constexpr enable_if_t<!B, descr<N2 - 1>> _(char const(&)[N1], char const(&text2)[N2]) { |
82 | 69 | return _(text2);
|
83 | 70 | }
|
84 |
| -template <bool B, size_t SizeA1, size_t SizeA2, size_t SizeB1, size_t SizeB2> |
85 |
| -constexpr enable_if_t<B, descr<SizeA1, SizeA2>> _(descr<SizeA1, SizeA2> d, descr<SizeB1, SizeB2>) { return d; } |
86 |
| -template <bool B, size_t SizeA1, size_t SizeA2, size_t SizeB1, size_t SizeB2> |
87 |
| -constexpr enable_if_t<!B, descr<SizeB1, SizeB2>> _(descr<SizeA1, SizeA2>, descr<SizeB1, SizeB2> d) { return d; } |
| 71 | + |
| 72 | +template <bool B, typename T1, typename T2> |
| 73 | +constexpr enable_if_t<B, T1> _(const T1 &d, const T2 &) { return d; } |
| 74 | +template <bool B, typename T1, typename T2> |
| 75 | +constexpr enable_if_t<!B, T2> _(const T1 &, const T2 &d) { return d; } |
88 | 76 |
|
89 | 77 | template <size_t Size> auto constexpr _() -> decltype(int_to_str<Size / 10, Size % 10>::digits) {
|
90 | 78 | return int_to_str<Size / 10, Size % 10>::digits;
|
91 | 79 | }
|
92 | 80 |
|
93 |
| -template <typename Type> constexpr descr<1, 1> _() { |
94 |
| - return descr<1, 1>({ '%', '\0' }, { &typeid(Type), nullptr }); |
95 |
| -} |
| 81 | +template <typename Type> constexpr descr<1, Type> _() { return {'%'}; } |
96 | 82 |
|
97 |
| -constexpr descr<0, 0> concat() { return _(""); } |
| 83 | +constexpr descr<0> concat() { return {}; } |
98 | 84 |
|
99 |
| -template <size_t Size1, size_t Size2> |
100 |
| -constexpr descr<Size1, Size2> concat(descr<Size1, Size2> descr) { return descr; } |
| 85 | +template <size_t N, typename... Ts> |
| 86 | +constexpr descr<N, Ts...> concat(const descr<N, Ts...> &descr) { return descr; } |
101 | 87 |
|
102 |
| -template <size_t Size1, size_t Size2, typename... Args> |
103 |
| -constexpr auto concat(descr<Size1, Size2> d, Args... args) |
104 |
| - -> decltype(descr<Size1 + 2, Size2>{} + concat(args...)) { |
| 88 | +template <size_t N, typename... Ts, typename... Args> |
| 89 | +constexpr auto concat(const descr<N, Ts...> &d, const Args &...args) |
| 90 | + -> decltype(std::declval<descr<N + 2, Ts...>>() + concat(args...)) { |
105 | 91 | return d + _(", ") + concat(args...);
|
106 | 92 | }
|
107 | 93 |
|
108 |
| -template <size_t Size1, size_t Size2> |
109 |
| -constexpr descr<Size1 + 2, Size2> type_descr(descr<Size1, Size2> descr) { |
| 94 | +template <size_t N, typename... Ts> |
| 95 | +constexpr descr<N + 2, Ts...> type_descr(const descr<N, Ts...> &descr) { |
110 | 96 | return _("{") + descr + _("}");
|
111 | 97 | }
|
112 | 98 |
|
|
0 commit comments