Make it possible to generate constexpr signatures in C++11 mode

The current C++14 constexpr signatures don't require relaxed constexpr,
but only `auto` return type deduction. To get around this in C++11,
the type caster's `name()` static member functions are turned into
`static constexpr auto` variables.
This commit is contained in:
Dean Moldovan 2017-07-02 11:48:56 +02:00
parent f94d759881
commit c10ac6cf1f
9 changed files with 103 additions and 178 deletions

View File

@ -778,7 +778,7 @@ template <typename T1, typename T2> struct is_copy_constructible<std::pair<T1, T
template <typename type> class type_caster_base : public type_caster_generic { template <typename type> class type_caster_base : public type_caster_generic {
using itype = intrinsic_t<type>; using itype = intrinsic_t<type>;
public: public:
static PYBIND11_DESCR name() { return type_descr(_<type>()); } static constexpr auto name = type_descr(_<type>());
type_caster_base() : type_caster_base(typeid(type)) { } type_caster_base() : type_caster_base(typeid(type)) { }
explicit type_caster_base(const std::type_info &info) : type_caster_generic(info) { } explicit type_caster_base(const std::type_info &info) : type_caster_generic(info) { }
@ -885,7 +885,7 @@ private:
"std::reference_wrapper<T> caster requires T to have a caster with an `T &` operator"); "std::reference_wrapper<T> caster requires T to have a caster with an `T &` operator");
public: public:
bool load(handle src, bool convert) { return subcaster.load(src, convert); } bool load(handle src, bool convert) { return subcaster.load(src, convert); }
static PYBIND11_DESCR name() { return caster_t::name(); } static constexpr auto name = caster_t::name;
static handle cast(const std::reference_wrapper<type> &src, return_value_policy policy, handle parent) { static handle cast(const std::reference_wrapper<type> &src, return_value_policy policy, handle parent) {
// It is definitely wrong to take ownership of this pointer, so mask that rvp // It is definitely wrong to take ownership of this pointer, so mask that rvp
if (policy == return_value_policy::take_ownership || policy == return_value_policy::automatic) if (policy == return_value_policy::take_ownership || policy == return_value_policy::automatic)
@ -900,7 +900,7 @@ public:
protected: \ protected: \
type value; \ type value; \
public: \ public: \
static PYBIND11_DESCR name() { return type_descr(py_name); } \ static constexpr auto name = type_descr(py_name); \
template <typename T_, enable_if_t<std::is_same<type, remove_cv_t<T_>>::value, int> = 0> \ template <typename T_, enable_if_t<std::is_same<type, remove_cv_t<T_>>::value, int> = 0> \
static handle cast(T_ *src, return_value_policy policy, handle parent) { \ static handle cast(T_ *src, return_value_policy policy, handle parent) { \
if (!src) return none().release(); \ if (!src) return none().release(); \
@ -1049,7 +1049,7 @@ public:
template <typename T> using cast_op_type = void*&; template <typename T> using cast_op_type = void*&;
operator void *&() { return value; } operator void *&() { return value; }
static PYBIND11_DESCR name() { return type_descr(_("capsule")); } static constexpr auto name = type_descr(_("capsule"));
private: private:
void *value = nullptr; void *value = nullptr;
}; };
@ -1289,7 +1289,7 @@ public:
return value[0]; return value[0];
} }
static PYBIND11_DESCR name() { return type_descr(_(PYBIND11_STRING_NAME)); } static constexpr auto name = type_descr(_(PYBIND11_STRING_NAME));
template <typename _T> using cast_op_type = remove_reference_t<pybind11::detail::cast_op_type<_T>>; template <typename _T> using cast_op_type = remove_reference_t<pybind11::detail::cast_op_type<_T>>;
}; };
@ -1314,9 +1314,9 @@ public:
return cast_impl(std::forward<T>(src), policy, parent, indices{}); return cast_impl(std::forward<T>(src), policy, parent, indices{});
} }
static PYBIND11_DESCR name() { static constexpr auto name = type_descr(
return type_descr(_("Tuple[") + detail::concat(make_caster<Ts>::name()...) + _("]")); _("Tuple[") + detail::concat(make_caster<Ts>::name...) + _("]")
} );
template <typename T> using cast_op_type = type; template <typename T> using cast_op_type = type;
@ -1461,7 +1461,7 @@ struct move_only_holder_caster {
auto *ptr = holder_helper<holder_type>::get(src); auto *ptr = holder_helper<holder_type>::get(src);
return type_caster_base<type>::cast_holder(ptr, &src); return type_caster_base<type>::cast_holder(ptr, &src);
} }
static PYBIND11_DESCR name() { return type_caster_base<type>::name(); } static constexpr auto name = type_caster_base<type>::name;
}; };
template <typename type, typename deleter> template <typename type, typename deleter>
@ -1492,10 +1492,10 @@ template <typename base, typename holder> struct is_holder_type :
template <typename base, typename deleter> struct is_holder_type<base, std::unique_ptr<base, deleter>> : template <typename base, typename deleter> struct is_holder_type<base, std::unique_ptr<base, deleter>> :
std::true_type {}; std::true_type {};
template <typename T> struct handle_type_name { static PYBIND11_DESCR name() { return _<T>(); } }; template <typename T> struct handle_type_name { static constexpr auto name = _<T>(); };
template <> struct handle_type_name<bytes> { static PYBIND11_DESCR name() { return _(PYBIND11_BYTES_NAME); } }; template <> struct handle_type_name<bytes> { static constexpr auto name = _(PYBIND11_BYTES_NAME); };
template <> struct handle_type_name<args> { static PYBIND11_DESCR name() { return _("*args"); } }; template <> struct handle_type_name<args> { static constexpr auto name = _("*args"); };
template <> struct handle_type_name<kwargs> { static PYBIND11_DESCR name() { return _("**kwargs"); } }; template <> struct handle_type_name<kwargs> { static constexpr auto name = _("**kwargs"); };
template <typename type> template <typename type>
struct pyobject_caster { struct pyobject_caster {
@ -1513,7 +1513,7 @@ struct pyobject_caster {
static handle cast(const handle &src, return_value_policy /* policy */, handle /* parent */) { static handle cast(const handle &src, return_value_policy /* policy */, handle /* parent */) {
return src.inc_ref(); return src.inc_ref();
} }
PYBIND11_TYPE_CASTER(type, handle_type_name<type>::name()); PYBIND11_TYPE_CASTER(type, handle_type_name<type>::name);
}; };
template <typename T> template <typename T>
@ -1826,7 +1826,7 @@ public:
static constexpr bool has_kwargs = kwargs_pos < 0; static constexpr bool has_kwargs = kwargs_pos < 0;
static constexpr bool has_args = args_pos < 0; static constexpr bool has_args = args_pos < 0;
static PYBIND11_DESCR arg_names() { return detail::concat(make_caster<Args>::name()...); } static constexpr auto arg_names = detail::concat(make_caster<Args>::name...);
bool load_args(function_call &call) { bool load_args(function_call &call) {
return load_impl_sequence(call, indices{}); return load_impl_sequence(call, indices{});

View File

@ -1,6 +1,5 @@
/* /*
pybind11/detail/descr.h: Helper type for concatenating type signatures pybind11/detail/descr.h: Helper type for concatenating type signatures at compile time
either at runtime (C++11) or compile time (C++14)
Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch> Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
@ -15,13 +14,12 @@
NAMESPACE_BEGIN(PYBIND11_NAMESPACE) NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
NAMESPACE_BEGIN(detail) NAMESPACE_BEGIN(detail)
/* Concatenate type signatures at compile time using C++14 */ /* Concatenate type signatures at compile time */
#if defined(PYBIND11_CPP14) && !defined(_MSC_VER)
#define PYBIND11_CONSTEXPR_DESCR
template <size_t Size1, size_t Size2> class descr { template <size_t Size1, size_t Size2> class descr {
template <size_t Size1_, size_t Size2_> friend class descr; template <size_t Size1_, size_t Size2_> friend class descr;
public: public:
constexpr descr() = default;
constexpr descr(char const (&text) [Size1+1], const std::type_info * const (&types)[Size2+1]) constexpr descr(char const (&text) [Size1+1], const std::type_info * const (&types)[Size2+1])
: descr(text, types, : descr(text, types,
make_index_sequence<Size1>(), make_index_sequence<Size1>(),
@ -96,90 +94,21 @@ template <typename Type> constexpr descr<1, 1> _() {
return descr<1, 1>({ '%', '\0' }, { &typeid(Type), nullptr }); return descr<1, 1>({ '%', '\0' }, { &typeid(Type), nullptr });
} }
inline constexpr descr<0, 0> concat() { return _(""); } constexpr descr<0, 0> concat() { return _(""); }
template <size_t Size1, size_t Size2, typename... Args> auto constexpr concat(descr<Size1, Size2> descr) { return descr; }
template <size_t Size1, size_t Size2, typename... Args> auto constexpr concat(descr<Size1, Size2> descr, Args&&... args) { return descr + _(", ") + concat(args...); }
template <size_t Size1, size_t Size2> auto constexpr type_descr(descr<Size1, Size2> descr) { return _("{") + descr + _("}"); }
#define PYBIND11_DESCR constexpr auto template <size_t Size1, size_t Size2>
constexpr descr<Size1, Size2> concat(descr<Size1, Size2> descr) { return descr; }
#else /* Simpler C++11 implementation based on run-time memory allocation and copying */ template <size_t Size1, size_t Size2, typename... Args>
constexpr auto concat(descr<Size1, Size2> d, Args... args)
class descr { -> decltype(descr<Size1 + 2, Size2>{} + concat(args...)) {
public: return d + _(", ") + concat(args...);
PYBIND11_NOINLINE descr(const char *text, const std::type_info * const * types) {
size_t nChars = len(text), nTypes = len(types);
m_text = new char[nChars];
m_types = new const std::type_info *[nTypes];
memcpy(m_text, text, nChars * sizeof(char));
memcpy(m_types, types, nTypes * sizeof(const std::type_info *));
}
PYBIND11_NOINLINE descr operator+(descr &&d2) && {
descr r;
size_t nChars1 = len(m_text), nTypes1 = len(m_types);
size_t nChars2 = len(d2.m_text), nTypes2 = len(d2.m_types);
r.m_text = new char[nChars1 + nChars2 - 1];
r.m_types = new const std::type_info *[nTypes1 + nTypes2 - 1];
memcpy(r.m_text, m_text, (nChars1-1) * sizeof(char));
memcpy(r.m_text + nChars1 - 1, d2.m_text, nChars2 * sizeof(char));
memcpy(r.m_types, m_types, (nTypes1-1) * sizeof(std::type_info *));
memcpy(r.m_types + nTypes1 - 1, d2.m_types, nTypes2 * sizeof(std::type_info *));
delete[] m_text; delete[] m_types;
delete[] d2.m_text; delete[] d2.m_types;
return r;
}
char *text() { return m_text; }
const std::type_info * * types() { return m_types; }
protected:
PYBIND11_NOINLINE descr() { }
template <typename T> static size_t len(const T *ptr) { // return length including null termination
const T *it = ptr;
while (*it++ != (T) 0)
;
return static_cast<size_t>(it - ptr);
}
const std::type_info **m_types = nullptr;
char *m_text = nullptr;
};
/* The 'PYBIND11_NOINLINE inline' combinations below are intentional to get the desired linkage while producing as little object code as possible */
PYBIND11_NOINLINE inline descr _(const char *text) {
const std::type_info *types[1] = { nullptr };
return descr(text, types);
} }
template <bool B> PYBIND11_NOINLINE enable_if_t<B, descr> _(const char *text1, const char *) { return _(text1); } template <size_t Size1, size_t Size2>
template <bool B> PYBIND11_NOINLINE enable_if_t<!B, descr> _(char const *, const char *text2) { return _(text2); } constexpr descr<Size1 + 2, Size2> type_descr(descr<Size1, Size2> descr) {
template <bool B> PYBIND11_NOINLINE enable_if_t<B, descr> _(descr d, descr) { return d; } return _("{") + descr + _("}");
template <bool B> PYBIND11_NOINLINE enable_if_t<!B, descr> _(descr, descr d) { return d; }
template <typename Type> PYBIND11_NOINLINE descr _() {
const std::type_info *types[2] = { &typeid(Type), nullptr };
return descr("%", types);
} }
template <size_t Size> PYBIND11_NOINLINE descr _() {
const std::type_info *types[1] = { nullptr };
return descr(std::to_string(Size).c_str(), types);
}
PYBIND11_NOINLINE inline descr concat() { return _(""); }
PYBIND11_NOINLINE inline descr concat(descr &&d) { return d; }
template <typename... Args> PYBIND11_NOINLINE descr concat(descr &&d, Args&&... args) { return std::move(d) + _(", ") + concat(std::forward<Args>(args)...); }
PYBIND11_NOINLINE inline descr type_descr(descr&& d) { return _("{") + std::move(d) + _("}"); }
#define PYBIND11_DESCR ::pybind11::detail::descr
#endif
NAMESPACE_END(detail) NAMESPACE_END(detail)
NAMESPACE_END(PYBIND11_NAMESPACE) NAMESPACE_END(PYBIND11_NAMESPACE)

View File

@ -24,7 +24,7 @@ public:
template <typename> using cast_op_type = value_and_holder &; template <typename> using cast_op_type = value_and_holder &;
operator value_and_holder &() { return *value; } operator value_and_holder &() { return *value; }
static PYBIND11_DESCR name() { return type_descr(_<value_and_holder>()); } static constexpr auto name = type_descr(_<value_and_holder>());
private: private:
value_and_holder *value = nullptr; value_and_holder *value = nullptr;

View File

@ -180,13 +180,13 @@ template <typename Type_> struct EigenProps {
} }
} }
static PYBIND11_DESCR descriptor() { static constexpr bool show_writeable = is_eigen_dense_map<Type>::value && is_eigen_mutable_map<Type>::value;
constexpr bool show_writeable = is_eigen_dense_map<Type>::value && is_eigen_mutable_map<Type>::value; static constexpr bool show_order = is_eigen_dense_map<Type>::value;
constexpr bool show_order = is_eigen_dense_map<Type>::value; static constexpr bool show_c_contiguous = show_order && requires_row_major;
constexpr bool show_c_contiguous = show_order && requires_row_major; static constexpr bool show_f_contiguous = !show_c_contiguous && show_order && requires_col_major;
constexpr bool show_f_contiguous = !show_c_contiguous && show_order && requires_col_major;
return type_descr(_("numpy.ndarray[") + npy_format_descriptor<Scalar>::name() + static constexpr auto descriptor = type_descr(
_("numpy.ndarray[") + npy_format_descriptor<Scalar>::name +
_("[") + _<fixed_rows>(_<(size_t) rows>(), _("m")) + _("[") + _<fixed_rows>(_<(size_t) rows>(), _("m")) +
_(", ") + _<fixed_cols>(_<(size_t) cols>(), _("n")) + _(", ") + _<fixed_cols>(_<(size_t) cols>(), _("n")) +
_("]") + _("]") +
@ -201,7 +201,6 @@ template <typename Type_> struct EigenProps {
_<show_f_contiguous>(", flags.f_contiguous", "") + _<show_f_contiguous>(", flags.f_contiguous", "") +
_("]") _("]")
); );
}
}; };
// Casts an Eigen type to numpy array. If given a base, the numpy array references the src data, // Casts an Eigen type to numpy array. If given a base, the numpy array references the src data,
@ -337,7 +336,7 @@ public:
return cast_impl(src, policy, parent); return cast_impl(src, policy, parent);
} }
static PYBIND11_DESCR name() { return props::descriptor(); } static constexpr auto name = props::descriptor;
operator Type*() { return &value; } operator Type*() { return &value; }
operator Type&() { return value; } operator Type&() { return value; }
@ -385,7 +384,7 @@ public:
} }
} }
static PYBIND11_DESCR name() { return props::descriptor(); } static constexpr auto name = props::descriptor;
// Explicitly delete these: support python -> C++ conversion on these (i.e. these can be return // Explicitly delete these: support python -> C++ conversion on these (i.e. these can be return
// types but not bound arguments). We still provide them (with an explicitly delete) so that // types but not bound arguments). We still provide them (with an explicitly delete) so that
@ -530,7 +529,7 @@ public:
} }
static handle cast(const Type *src, return_value_policy policy, handle parent) { return cast(*src, policy, parent); } static handle cast(const Type *src, return_value_policy policy, handle parent) { return cast(*src, policy, parent); }
static PYBIND11_DESCR name() { return props::descriptor(); } static constexpr auto name = props::descriptor;
// Explicitly delete these: support python -> C++ conversion on these (i.e. these can be return // Explicitly delete these: support python -> C++ conversion on these (i.e. these can be return
// types but not bound arguments). We still provide them (with an explicitly delete) so that // types but not bound arguments). We still provide them (with an explicitly delete) so that
@ -597,7 +596,7 @@ struct type_caster<Type, enable_if_t<is_eigen_sparse<Type>::value>> {
} }
PYBIND11_TYPE_CASTER(Type, _<(Type::IsRowMajor) != 0>("scipy.sparse.csr_matrix[", "scipy.sparse.csc_matrix[") PYBIND11_TYPE_CASTER(Type, _<(Type::IsRowMajor) != 0>("scipy.sparse.csr_matrix[", "scipy.sparse.csc_matrix[")
+ npy_format_descriptor<Scalar>::name() + _("]")); + npy_format_descriptor<Scalar>::name + _("]"));
}; };
NAMESPACE_END(detail) NAMESPACE_END(detail)

View File

@ -75,10 +75,8 @@ public:
return cpp_function(std::forward<Func>(f_), policy).release(); return cpp_function(std::forward<Func>(f_), policy).release();
} }
PYBIND11_TYPE_CASTER(type, _("Callable[[") + PYBIND11_TYPE_CASTER(type, _("Callable[[") + argument_loader<Args...>::arg_names + _("], ")
argument_loader<Args...>::arg_names() + _("], ") + + make_caster<retval_type>::name + _("]"));
make_caster<retval_type>::name() +
_("]"));
}; };
NAMESPACE_END(detail) NAMESPACE_END(detail)

View File

@ -250,7 +250,7 @@ template <typename T> struct array_info_scalar {
typedef T type; typedef T type;
static constexpr bool is_array = false; static constexpr bool is_array = false;
static constexpr bool is_empty = false; static constexpr bool is_empty = false;
static PYBIND11_DESCR extents() { return _(""); } static constexpr auto extents = _("");
static void append_extents(list& /* shape */) { } static void append_extents(list& /* shape */) { }
}; };
// Computes underlying type and a comma-separated list of extents for array // Computes underlying type and a comma-separated list of extents for array
@ -269,15 +269,9 @@ template <typename T, size_t N> struct array_info<std::array<T, N>> {
array_info<T>::append_extents(shape); array_info<T>::append_extents(shape);
} }
template<typename T2 = T, enable_if_t<!array_info<T2>::is_array, int> = 0> static constexpr auto extents = _<array_info<T>::is_array>(
static PYBIND11_DESCR extents() { concat(_<N>(), array_info<T>::extents), _<N>()
return _<N>(); );
}
template<typename T2 = T, enable_if_t<array_info<T2>::is_array, int> = 0>
static PYBIND11_DESCR extents() {
return concat(_<N>(), array_info<T>::extents());
}
}; };
// For numpy we have special handling for arrays of characters, so we don't include // For numpy we have special handling for arrays of characters, so we don't include
// the size in the array extents. // the size in the array extents.
@ -947,7 +941,7 @@ template <typename T>
struct format_descriptor<T, detail::enable_if_t<detail::array_info<T>::is_array>> { struct format_descriptor<T, detail::enable_if_t<detail::array_info<T>::is_array>> {
static std::string format() { static std::string format() {
using detail::_; using detail::_;
PYBIND11_DESCR extents = _("(") + detail::array_info<T>::extents() + _(")"); constexpr auto extents = _("(") + detail::array_info<T>::extents + _(")");
return extents.text() + format_descriptor<detail::remove_all_extents_t<T>>::format(); return extents.text() + format_descriptor<detail::remove_all_extents_t<T>>::format();
} }
}; };
@ -967,7 +961,7 @@ struct pyobject_caster<array_t<T, ExtraFlags>> {
static handle cast(const handle &src, return_value_policy /* policy */, handle /* parent */) { static handle cast(const handle &src, return_value_policy /* policy */, handle /* parent */) {
return src.inc_ref(); return src.inc_ref();
} }
PYBIND11_TYPE_CASTER(type, handle_type_name<type>::name()); PYBIND11_TYPE_CASTER(type, handle_type_name<type>::name);
}; };
template <typename T> template <typename T>
@ -977,7 +971,34 @@ struct compare_buffer_info<T, detail::enable_if_t<detail::is_pod_struct<T>::valu
} }
}; };
template <typename T> struct npy_format_descriptor<T, enable_if_t<satisfies_any_of<T, std::is_arithmetic, is_complex>::value>> { template <typename T, typename = void>
struct npy_format_descriptor_name;
template <typename T>
struct npy_format_descriptor_name<T, enable_if_t<std::is_integral<T>::value>> {
static constexpr auto name = _<std::is_same<T, bool>::value>(
_("bool"), _<std::is_signed<T>::value>("int", "uint") + _<sizeof(T)*8>()
);
};
template <typename T>
struct npy_format_descriptor_name<T, enable_if_t<std::is_floating_point<T>::value>> {
static constexpr auto name = _<std::is_same<T, float>::value || std::is_same<T, double>::value>(
_("float") + _<sizeof(T)*8>(), _("longdouble")
);
};
template <typename T>
struct npy_format_descriptor_name<T, enable_if_t<is_complex<T>::value>> {
static constexpr auto name = _<std::is_same<typename T::value_type, float>::value
|| std::is_same<typename T::value_type, double>::value>(
_("complex") + _<sizeof(typename T::value_type)*16>(), _("longcomplex")
);
};
template <typename T>
struct npy_format_descriptor<T, enable_if_t<satisfies_any_of<T, std::is_arithmetic, is_complex>::value>>
: npy_format_descriptor_name<T> {
private: private:
// NB: the order here must match the one in common.h // NB: the order here must match the one in common.h
constexpr static const int values[15] = { constexpr static const int values[15] = {
@ -996,25 +1017,10 @@ public:
return reinterpret_borrow<pybind11::dtype>(ptr); return reinterpret_borrow<pybind11::dtype>(ptr);
pybind11_fail("Unsupported buffer format!"); pybind11_fail("Unsupported buffer format!");
} }
template <typename T2 = T, enable_if_t<std::is_integral<T2>::value, int> = 0>
static PYBIND11_DESCR name() {
return _<std::is_same<T, bool>::value>(_("bool"),
_<std::is_signed<T>::value>("int", "uint") + _<sizeof(T)*8>());
}
template <typename T2 = T, enable_if_t<std::is_floating_point<T2>::value, int> = 0>
static PYBIND11_DESCR name() {
return _<std::is_same<T, float>::value || std::is_same<T, double>::value>(
_("float") + _<sizeof(T)*8>(), _("longdouble"));
}
template <typename T2 = T, enable_if_t<is_complex<T2>::value, int> = 0>
static PYBIND11_DESCR name() {
return _<std::is_same<typename T2::value_type, float>::value || std::is_same<typename T2::value_type, double>::value>(
_("complex") + _<sizeof(typename T2::value_type)*16>(), _("longcomplex"));
}
}; };
#define PYBIND11_DECL_CHAR_FMT \ #define PYBIND11_DECL_CHAR_FMT \
static PYBIND11_DESCR name() { return _("S") + _<N>(); } \ static constexpr auto name = _("S") + _<N>(); \
static pybind11::dtype dtype() { return pybind11::dtype(std::string("S") + std::to_string(N)); } static pybind11::dtype dtype() { return pybind11::dtype(std::string("S") + std::to_string(N)); }
template <size_t N> struct npy_format_descriptor<char[N]> { PYBIND11_DECL_CHAR_FMT }; template <size_t N> struct npy_format_descriptor<char[N]> { PYBIND11_DECL_CHAR_FMT };
template <size_t N> struct npy_format_descriptor<std::array<char, N>> { PYBIND11_DECL_CHAR_FMT }; template <size_t N> struct npy_format_descriptor<std::array<char, N>> { PYBIND11_DECL_CHAR_FMT };
@ -1026,7 +1032,7 @@ private:
public: public:
static_assert(!array_info<T>::is_empty, "Zero-sized arrays are not supported"); static_assert(!array_info<T>::is_empty, "Zero-sized arrays are not supported");
static PYBIND11_DESCR name() { return _("(") + array_info<T>::extents() + _(")") + base_descr::name(); } static constexpr auto name = _("(") + array_info<T>::extents + _(")") + base_descr::name;
static pybind11::dtype dtype() { static pybind11::dtype dtype() {
list shape; list shape;
array_info<T>::append_extents(shape); array_info<T>::append_extents(shape);
@ -1038,7 +1044,7 @@ template<typename T> struct npy_format_descriptor<T, enable_if_t<std::is_enum<T>
private: private:
using base_descr = npy_format_descriptor<typename std::underlying_type<T>::type>; using base_descr = npy_format_descriptor<typename std::underlying_type<T>::type>;
public: public:
static PYBIND11_DESCR name() { return base_descr::name(); } static constexpr auto name = base_descr::name;
static pybind11::dtype dtype() { return base_descr::dtype(); } static pybind11::dtype dtype() { return base_descr::dtype(); }
}; };
@ -1113,7 +1119,7 @@ inline PYBIND11_NOINLINE void register_structured_dtype(
template <typename T, typename SFINAE> struct npy_format_descriptor { template <typename T, typename SFINAE> struct npy_format_descriptor {
static_assert(is_pod_struct<T>::value, "Attempt to use a non-POD or unimplemented POD type as a numpy dtype"); static_assert(is_pod_struct<T>::value, "Attempt to use a non-POD or unimplemented POD type as a numpy dtype");
static PYBIND11_DESCR name() { return make_caster<T>::name(); } static constexpr auto name = make_caster<T>::name;
static pybind11::dtype dtype() { static pybind11::dtype dtype() {
return reinterpret_borrow<pybind11::dtype>(dtype_ptr()); return reinterpret_borrow<pybind11::dtype>(dtype_ptr());
@ -1558,9 +1564,7 @@ vectorize_extractor(const Func &f, Return (*) (Args ...)) {
} }
template <typename T, int Flags> struct handle_type_name<array_t<T, Flags>> { template <typename T, int Flags> struct handle_type_name<array_t<T, Flags>> {
static PYBIND11_DESCR name() { static constexpr auto name = _("numpy.ndarray[") + npy_format_descriptor<T>::name + _("]");
return _("numpy.ndarray[") + npy_format_descriptor<T>::name() + _("]");
}
}; };
NAMESPACE_END(detail) NAMESPACE_END(detail)

View File

@ -164,7 +164,7 @@ protected:
/* Generate a readable signature describing the function's arguments and return value types */ /* Generate a readable signature describing the function's arguments and return value types */
using detail::descr; using detail::_; using detail::descr; using detail::_;
PYBIND11_DESCR signature = _("(") + cast_in::arg_names() + _(") -> ") + cast_out::name(); constexpr auto signature = _("(") + cast_in::arg_names + _(") -> ") + cast_out::name;
/* Register the function with Python from generic (non-templated) code */ /* Register the function with Python from generic (non-templated) code */
initialize_generic(rec, signature.text(), signature.types(), sizeof...(Args)); initialize_generic(rec, signature.text(), signature.types(), sizeof...(Args));
@ -275,11 +275,6 @@ protected:
if (type_depth != 0 || types[type_index] != nullptr) if (type_depth != 0 || types[type_index] != nullptr)
pybind11_fail("Internal error while parsing type signature (2)"); pybind11_fail("Internal error while parsing type signature (2)");
#if !defined(PYBIND11_CONSTEXPR_DESCR)
delete[] types;
delete[] text;
#endif
#if PY_MAJOR_VERSION < 3 #if PY_MAJOR_VERSION < 3
if (strcmp(rec->name, "__next__") == 0) { if (strcmp(rec->name, "__next__") == 0) {
std::free(rec->name); std::free(rec->name);

View File

@ -91,7 +91,7 @@ template <typename Type, typename Key> struct set_caster {
return s.release(); return s.release();
} }
PYBIND11_TYPE_CASTER(type, _("Set[") + key_conv::name() + _("]")); PYBIND11_TYPE_CASTER(type, _("Set[") + key_conv::name + _("]"));
}; };
template <typename Type, typename Key, typename Value> struct map_caster { template <typename Type, typename Key, typename Value> struct map_caster {
@ -127,7 +127,7 @@ template <typename Type, typename Key, typename Value> struct map_caster {
return d.release(); return d.release();
} }
PYBIND11_TYPE_CASTER(Type, _("Dict[") + key_conv::name() + _(", ") + value_conv::name() + _("]")); PYBIND11_TYPE_CASTER(Type, _("Dict[") + key_conv::name + _(", ") + value_conv::name + _("]"));
}; };
template <typename Type, typename Value> struct list_caster { template <typename Type, typename Value> struct list_caster {
@ -168,7 +168,7 @@ public:
return l.release(); return l.release();
} }
PYBIND11_TYPE_CASTER(Type, _("List[") + value_conv::name() + _("]")); PYBIND11_TYPE_CASTER(Type, _("List[") + value_conv::name + _("]"));
}; };
template <typename Type, typename Alloc> struct type_caster<std::vector<Type, Alloc>> template <typename Type, typename Alloc> struct type_caster<std::vector<Type, Alloc>>
@ -222,7 +222,7 @@ public:
return l.release(); return l.release();
} }
PYBIND11_TYPE_CASTER(ArrayType, _("List[") + value_conv::name() + _<Resizable>(_(""), _("[") + _<Size>() + _("]")) + _("]")); PYBIND11_TYPE_CASTER(ArrayType, _("List[") + value_conv::name + _<Resizable>(_(""), _("[") + _<Size>() + _("]")) + _("]"));
}; };
template <typename Type, size_t Size> struct type_caster<std::array<Type, Size>> template <typename Type, size_t Size> struct type_caster<std::array<Type, Size>>
@ -268,7 +268,7 @@ template<typename T> struct optional_caster {
return true; return true;
} }
PYBIND11_TYPE_CASTER(T, _("Optional[") + value_conv::name() + _("]")); PYBIND11_TYPE_CASTER(T, _("Optional[") + value_conv::name + _("]"));
}; };
#if PYBIND11_HAS_OPTIONAL #if PYBIND11_HAS_OPTIONAL
@ -348,7 +348,7 @@ struct variant_caster<V<Ts...>> {
} }
using Type = V<Ts...>; using Type = V<Ts...>;
PYBIND11_TYPE_CASTER(Type, _("Union[") + detail::concat(make_caster<Ts>::name()...) + _("]")); PYBIND11_TYPE_CASTER(Type, _("Union[") + detail::concat(make_caster<Ts>::name...) + _("]"));
}; };
#if PYBIND11_HAS_VARIANT #if PYBIND11_HAS_VARIANT

View File

@ -86,7 +86,7 @@ template <> struct type_caster<CopyOnlyInt> {
protected: protected:
CopyOnlyInt value; CopyOnlyInt value;
public: public:
static PYBIND11_DESCR name() { return _("CopyOnlyInt"); } static constexpr auto name = _("CopyOnlyInt");
bool load(handle src, bool) { value = CopyOnlyInt(src.cast<int>()); return true; } bool load(handle src, bool) { value = CopyOnlyInt(src.cast<int>()); return true; }
static handle cast(const CopyOnlyInt &m, return_value_policy r, handle p) { return pybind11::cast(m.value, r, p); } static handle cast(const CopyOnlyInt &m, return_value_policy r, handle p) { return pybind11::cast(m.value, r, p); }
static handle cast(const CopyOnlyInt *src, return_value_policy policy, handle parent) { static handle cast(const CopyOnlyInt *src, return_value_policy policy, handle parent) {