diff --git a/include/pybind11/attr.h b/include/pybind11/attr.h index 6c413284..9acb3e3a 100644 --- a/include/pybind11/attr.h +++ b/include/pybind11/attr.h @@ -14,30 +14,6 @@ NAMESPACE_BEGIN(pybind11) -/// Annotation for keyword arguments -struct arg { - constexpr explicit arg(const char *name) : name(name) { } - - template - constexpr arg_t operator=(const T &value) const { return {name, value}; } - - const char *name; -}; - -/// Annotation for keyword arguments with default values -template struct arg_t : public arg { - constexpr arg_t(const char *name, const T &value, const char *descr = nullptr) - : arg(name), value(&value), descr(descr) { } - - const T *value; - const char *descr; -}; - -inline namespace literals { -/// String literal version of arg -constexpr arg operator"" _a(const char *name, size_t) { return arg(name); } -} - /// Annotation for methods struct is_method { handle class_; is_method(const handle &c) : class_(c) { } }; @@ -233,21 +209,14 @@ template <> struct process_attribute : process_attribute_default { }; /// Process a keyword argument attribute (*with* a default value) -template -struct process_attribute> : process_attribute_default> { - static void init(const arg_t &a, function_record *r) { +template <> struct process_attribute : process_attribute_default { + static void init(const arg_v &a, function_record *r) { if (r->class_ && r->args.empty()) r->args.emplace_back("self", nullptr, handle()); - /* Convert keyword value into a Python object */ - auto o = object(detail::make_caster::cast( - *a.value, return_value_policy::automatic, handle()), false); - - if (!o) { + if (!a.value) { #if !defined(NDEBUG) - std::string descr(typeid(T).name()); - detail::clean_type_id(descr); - descr = "'" + std::string(a.name) + ": " + descr + "'"; + auto descr = "'" + std::string(a.name) + ": " + a.type + "'"; if (r->class_) { if (r->name) descr += " in method '" + (std::string) r->class_.str() + "." + (std::string) r->name + "'"; @@ -264,7 +233,7 @@ struct process_attribute> : process_attribute_default> { "Compile in debug mode for more information."); #endif } - r->args.emplace_back(a.name, a.descr, o.release()); + r->args.emplace_back(a.name, a.descr, a.value.inc_ref()); } }; diff --git a/include/pybind11/cast.h b/include/pybind11/cast.h index 213fbd2e..c8c8f77b 100644 --- a/include/pybind11/cast.h +++ b/include/pybind11/cast.h @@ -949,6 +949,44 @@ template arg_v operator=(T &&value) const; + + const char *name; +}; + +/// Annotation for keyword arguments with values +struct arg_v : arg { + template + arg_v(const char *name, T &&x, const char *descr = nullptr) + : arg(name), + value(detail::make_caster::cast(x, return_value_policy::automatic, handle()), false), + descr(descr) +#if !defined(NDEBUG) + , type(type_id()) +#endif + { } + + object value; + const char *descr; +#if !defined(NDEBUG) + std::string type; +#endif +}; + +template +arg_v arg::operator=(T &&value) const { return {name, std::forward(value)}; } + +/// Alias for backward compatibility -- to be remove in version 2.0 +template using arg_t = arg_v; + +inline namespace literals { +/// String literal version of arg +constexpr arg operator"" _a(const char *name, size_t) { return arg(name); } +} + NAMESPACE_BEGIN(detail) NAMESPACE_BEGIN(constexpr_impl) /// Implementation details for constexpr functions @@ -1044,8 +1082,7 @@ private: } } - template - void process(list &/*args_list*/, arg_t &&a) { + void process(list &/*args_list*/, arg_v a) { if (m_kwargs[a.name]) { #if defined(NDEBUG) multiple_values_error(); @@ -1053,15 +1090,14 @@ private: multiple_values_error(a.name); #endif } - auto o = object(detail::make_caster::cast(*a.value, policy, nullptr), false); - if (!o) { + if (!a.value) { #if defined(NDEBUG) argument_cast_error(); #else - argument_cast_error(a.name, type_id()); + argument_cast_error(a.name, a.type); #endif } - m_kwargs[a.name] = o; + m_kwargs[a.name] = a.value; } void process(list &/*args_list*/, detail::kwargs_proxy kp) { diff --git a/include/pybind11/pytypes.h b/include/pybind11/pytypes.h index d7fda31d..51f16291 100644 --- a/include/pybind11/pytypes.h +++ b/include/pybind11/pytypes.h @@ -17,7 +17,7 @@ NAMESPACE_BEGIN(pybind11) /* A few forward declarations */ class object; class str; class iterator; -struct arg; template struct arg_t; +struct arg; struct arg_v; namespace detail { class accessor; class args_proxy; class kwargs_proxy; } /// Holds a reference to a Python object (no reference counting)