File indexing completed on 2025-02-23 05:15:01
0001 /* 0002 pybind11/detail/descr.h: Helper type for concatenating type signatures at compile time 0003 0004 Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch> 0005 0006 All rights reserved. Use of this source code is governed by a 0007 BSD-style license that can be found in the LICENSE file. 0008 */ 0009 0010 #pragma once 0011 0012 #include "common.h" 0013 0014 PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) 0015 PYBIND11_NAMESPACE_BEGIN(detail) 0016 0017 #if !defined(_MSC_VER) 0018 # define PYBIND11_DESCR_CONSTEXPR static constexpr 0019 #else 0020 # define PYBIND11_DESCR_CONSTEXPR const 0021 #endif 0022 0023 /* Concatenate type signatures at compile time */ 0024 template <size_t N, typename... Ts> 0025 struct descr { 0026 char text[N + 1]{'\0'}; 0027 0028 constexpr descr() = default; 0029 // NOLINTNEXTLINE(google-explicit-constructor) 0030 constexpr descr(char const (&s)[N+1]) : descr(s, make_index_sequence<N>()) { } 0031 0032 template <size_t... Is> 0033 constexpr descr(char const (&s)[N+1], index_sequence<Is...>) : text{s[Is]..., '\0'} { } 0034 0035 template <typename... Chars> 0036 // NOLINTNEXTLINE(google-explicit-constructor) 0037 constexpr descr(char c, Chars... cs) : text{c, static_cast<char>(cs)..., '\0'} { } 0038 0039 static constexpr std::array<const std::type_info *, sizeof...(Ts) + 1> types() { 0040 return {{&typeid(Ts)..., nullptr}}; 0041 } 0042 }; 0043 0044 template <size_t N1, size_t N2, typename... Ts1, typename... Ts2, size_t... Is1, size_t... Is2> 0045 constexpr descr<N1 + N2, Ts1..., Ts2...> plus_impl(const descr<N1, Ts1...> &a, const descr<N2, Ts2...> &b, 0046 index_sequence<Is1...>, index_sequence<Is2...>) { 0047 PYBIND11_WORKAROUND_INCORRECT_MSVC_C4100(b); 0048 return {a.text[Is1]..., b.text[Is2]...}; 0049 } 0050 0051 template <size_t N1, size_t N2, typename... Ts1, typename... Ts2> 0052 constexpr descr<N1 + N2, Ts1..., Ts2...> operator+(const descr<N1, Ts1...> &a, const descr<N2, Ts2...> &b) { 0053 return plus_impl(a, b, make_index_sequence<N1>(), make_index_sequence<N2>()); 0054 } 0055 0056 template <size_t N> 0057 constexpr descr<N - 1> const_name(char const(&text)[N]) { return descr<N - 1>(text); } 0058 constexpr descr<0> const_name(char const(&)[1]) { return {}; } 0059 0060 template <size_t Rem, size_t... Digits> struct int_to_str : int_to_str<Rem/10, Rem%10, Digits...> { }; 0061 template <size_t...Digits> struct int_to_str<0, Digits...> { 0062 // WARNING: This only works with C++17 or higher. 0063 static constexpr auto digits = descr<sizeof...(Digits)>(('0' + Digits)...); 0064 }; 0065 0066 // Ternary description (like std::conditional) 0067 template <bool B, size_t N1, size_t N2> 0068 constexpr enable_if_t<B, descr<N1 - 1>> const_name(char const(&text1)[N1], char const(&)[N2]) { 0069 return const_name(text1); 0070 } 0071 template <bool B, size_t N1, size_t N2> 0072 constexpr enable_if_t<!B, descr<N2 - 1>> const_name(char const(&)[N1], char const(&text2)[N2]) { 0073 return const_name(text2); 0074 } 0075 0076 template <bool B, typename T1, typename T2> 0077 constexpr enable_if_t<B, T1> const_name(const T1 &d, const T2 &) { return d; } 0078 template <bool B, typename T1, typename T2> 0079 constexpr enable_if_t<!B, T2> const_name(const T1 &, const T2 &d) { return d; } 0080 0081 template <size_t Size> 0082 auto constexpr const_name() -> remove_cv_t<decltype(int_to_str<Size / 10, Size % 10>::digits)> { 0083 return int_to_str<Size / 10, Size % 10>::digits; 0084 } 0085 0086 template <typename Type> constexpr descr<1, Type> const_name() { return {'%'}; } 0087 0088 // If "_" is defined as a macro, py::detail::_ cannot be provided. 0089 // It is therefore best to use py::detail::const_name universally. 0090 // This block is for backward compatibility only. 0091 // (The const_name code is repeated to avoid introducing a "_" #define ourselves.) 0092 #ifndef _ 0093 #define PYBIND11_DETAIL_UNDERSCORE_BACKWARD_COMPATIBILITY 0094 template <size_t N> 0095 constexpr descr<N-1> _(char const(&text)[N]) { return const_name<N>(text); } 0096 template <bool B, size_t N1, size_t N2> 0097 constexpr enable_if_t<B, descr<N1 - 1>> _(char const(&text1)[N1], char const(&text2)[N2]) { 0098 return const_name<B,N1,N2>(text1, text2); 0099 } 0100 template <bool B, size_t N1, size_t N2> 0101 constexpr enable_if_t<!B, descr<N2 - 1>> _(char const(&text1)[N1], char const(&text2)[N2]) { 0102 return const_name<B,N1,N2>(text1, text2); 0103 } 0104 template <bool B, typename T1, typename T2> 0105 constexpr enable_if_t<B, T1> _(const T1 &d1, const T2 &d2) { return const_name<B,T1,T2>(d1, d2); } 0106 template <bool B, typename T1, typename T2> 0107 constexpr enable_if_t<!B, T2> _(const T1 &d1, const T2 &d2) { return const_name<B,T1,T2>(d1, d2); } 0108 0109 template <size_t Size> 0110 auto constexpr _() -> remove_cv_t<decltype(int_to_str<Size / 10, Size % 10>::digits)> { 0111 return const_name<Size>(); 0112 } 0113 template <typename Type> constexpr descr<1, Type> _() { return const_name<Type>(); } 0114 #endif // #ifndef _ 0115 0116 constexpr descr<0> concat() { return {}; } 0117 0118 template <size_t N, typename... Ts> 0119 constexpr descr<N, Ts...> concat(const descr<N, Ts...> &descr) { return descr; } 0120 0121 template <size_t N, typename... Ts, typename... Args> 0122 constexpr auto concat(const descr<N, Ts...> &d, const Args &...args) 0123 -> decltype(std::declval<descr<N + 2, Ts...>>() + concat(args...)) { 0124 return d + const_name(", ") + concat(args...); 0125 } 0126 0127 template <size_t N, typename... Ts> 0128 constexpr descr<N + 2, Ts...> type_descr(const descr<N, Ts...> &descr) { 0129 return const_name("{") + descr + const_name("}"); 0130 } 0131 0132 PYBIND11_NAMESPACE_END(detail) 0133 PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)