diff --git a/include/pybind11/detail/init.h b/include/pybind11/detail/init.h index 79cc930c8d..5ecf0b4b0a 100644 --- a/include/pybind11/detail/init.h +++ b/include/pybind11/detail/init.h @@ -201,14 +201,14 @@ void construct(value_and_holder &v_h, Alias &&result, bool) { template struct constructor { template = 0> - static void execute(Class &cl, const Extra &...extra) { + static void execute(Class &cl, Extra &&...extra) { cl.def( "__init__", [](value_and_holder &v_h, Args... args) { v_h.value_ptr() = construct_or_initialize>(std::forward(args)...); }, is_new_style_constructor(), - extra...); + std::forward(extra)...); } template < @@ -216,7 +216,7 @@ struct constructor { typename... Extra, enable_if_t, Args...>::value, int> = 0> - static void execute(Class &cl, const Extra &...extra) { + static void execute(Class &cl, Extra &&...extra) { cl.def( "__init__", [](value_and_holder &v_h, Args... args) { @@ -229,7 +229,7 @@ struct constructor { } }, is_new_style_constructor(), - extra...); + std::forward(extra)...); } template < @@ -237,7 +237,7 @@ struct constructor { typename... Extra, enable_if_t, Args...>::value, int> = 0> - static void execute(Class &cl, const Extra &...extra) { + static void execute(Class &cl, Extra &&...extra) { cl.def( "__init__", [](value_and_holder &v_h, Args... args) { @@ -245,7 +245,7 @@ struct constructor { = construct_or_initialize>(std::forward(args)...); }, is_new_style_constructor(), - extra...); + std::forward(extra)...); } }; @@ -257,7 +257,7 @@ struct alias_constructor { typename... Extra, enable_if_t, Args...>::value, int> = 0> - static void execute(Class &cl, const Extra &...extra) { + static void execute(Class &cl, Extra &&...extra) { cl.def( "__init__", [](value_and_holder &v_h, Args... args) { @@ -265,7 +265,7 @@ struct alias_constructor { = construct_or_initialize>(std::forward(args)...); }, is_new_style_constructor(), - extra...); + std::forward(extra)...); } }; @@ -290,7 +290,7 @@ struct factory { // inheriting from the C++ type) the returned value needs to either already be an alias // instance, or the alias needs to be constructible from a `Class &&` argument. template - void execute(Class &cl, const Extra &...extra) && { + void execute(Class &cl, Extra &&...extra) && { #if defined(PYBIND11_CPP14) cl.def( "__init__", @@ -306,7 +306,7 @@ struct factory { v_h, func(std::forward(args)...), Py_TYPE(v_h.inst) != v_h.type->type); }, is_new_style_constructor(), - extra...); + std::forward(extra)...); } }; @@ -334,7 +334,7 @@ struct factory { // The class factory is called when the `self` type passed to `__init__` is the direct // class (i.e. not inherited), the alias factory when `self` is a Python-side subtype. template - void execute(Class &cl, const Extra &...extra) && { + void execute(Class &cl, Extra &&...extra) && { static_assert(Class::has_alias, "The two-argument version of `py::init()` can " "only be used if the class has an alias"); @@ -359,7 +359,7 @@ struct factory { } }, is_new_style_constructor(), - extra...); + std::forward(extra)...); } }; @@ -409,7 +409,7 @@ struct pickle_factory { pickle_factory(Get get, Set set) : get(std::forward(get)), set(std::forward(set)) {} template - void execute(Class &cl, const Extra &...extra) && { + void execute(Class &cl, Extra &&...extra) && { cl.def("__getstate__", std::move(get)); #if defined(PYBIND11_CPP14) @@ -427,7 +427,7 @@ struct pickle_factory { v_h, func(std::forward(state)), Py_TYPE(v_h.inst) != v_h.type->type); }, is_new_style_constructor(), - extra...); + std::forward(extra)...); } }; diff --git a/include/pybind11/operators.h b/include/pybind11/operators.h index 16a88ae171..92bcb9a671 100644 --- a/include/pybind11/operators.h +++ b/include/pybind11/operators.h @@ -86,20 +86,20 @@ template struct op_ { static constexpr bool op_enable_if_hook = true; template - void execute(Class &cl, const Extra &...extra) const { + void execute(Class &cl, Extra &&...extra) const { using Base = typename Class::type; using L_type = conditional_t::value, Base, L>; using R_type = conditional_t::value, Base, R>; using op = op_impl; - cl.def(op::name(), &op::execute, is_operator(), extra...); + cl.def(op::name(), &op::execute, is_operator(), std::forward(extra)...); } template - void execute_cast(Class &cl, const Extra &...extra) const { + void execute_cast(Class &cl, Extra &&...extra) const { using Base = typename Class::type; using L_type = conditional_t::value, Base, L>; using R_type = conditional_t::value, Base, R>; using op = op_impl; - cl.def(op::name(), &op::execute_cast, is_operator(), extra...); + cl.def(op::name(), &op::execute_cast, is_operator(), std::forward(extra)...); } }; diff --git a/include/pybind11/pybind11.h b/include/pybind11/pybind11.h index bcdf641f43..881c9863d3 100644 --- a/include/pybind11/pybind11.h +++ b/include/pybind11/pybind11.h @@ -110,12 +110,13 @@ class cpp_function : public function { // NOLINTNEXTLINE(google-explicit-constructor) cpp_function(std::nullptr_t) {} cpp_function(std::nullptr_t, const is_setter &) {} + cpp_function(std::nullptr_t, is_setter &&) {} /// Construct a cpp_function from a vanilla function pointer template // NOLINTNEXTLINE(google-explicit-constructor) - cpp_function(Return (*f)(Args...), const Extra &...extra) { - initialize(f, f, extra...); + cpp_function(Return (*f)(Args...), Extra &&...extra) { + initialize(f, f, std::forward(extra)...); } /// Construct a cpp_function from a lambda function (possibly with internal state) @@ -123,19 +124,20 @@ class cpp_function : public function { typename... Extra, typename = detail::enable_if_t::value>> // NOLINTNEXTLINE(google-explicit-constructor) - cpp_function(Func &&f, const Extra &...extra) { - initialize( - std::forward(f), (detail::function_signature_t *) nullptr, extra...); + cpp_function(Func &&f, Extra &&...extra) { + initialize(std::forward(f), + (detail::function_signature_t *) nullptr, + std::forward(extra)...); } /// Construct a cpp_function from a class method (non-const, no ref-qualifier) template // NOLINTNEXTLINE(google-explicit-constructor) - cpp_function(Return (Class::*f)(Arg...), const Extra &...extra) { + cpp_function(Return (Class::*f)(Arg...), Extra &&...extra) { initialize( [f](Class *c, Arg... args) -> Return { return (c->*f)(std::forward(args)...); }, (Return(*)(Class *, Arg...)) nullptr, - extra...); + std::forward(extra)...); } /// Construct a cpp_function from a class method (non-const, lvalue ref-qualifier) @@ -143,21 +145,21 @@ class cpp_function : public function { /// but with an added `&`. template // NOLINTNEXTLINE(google-explicit-constructor) - cpp_function(Return (Class::*f)(Arg...) &, const Extra &...extra) { + cpp_function(Return (Class::*f)(Arg...) &, Extra &&...extra) { initialize( [f](Class *c, Arg... args) -> Return { return (c->*f)(std::forward(args)...); }, (Return(*)(Class *, Arg...)) nullptr, - extra...); + std::forward(extra)...); } /// Construct a cpp_function from a class method (const, no ref-qualifier) template // NOLINTNEXTLINE(google-explicit-constructor) - cpp_function(Return (Class::*f)(Arg...) const, const Extra &...extra) { + cpp_function(Return (Class::*f)(Arg...) const, Extra &&...extra) { initialize([f](const Class *c, Arg... args) -> Return { return (c->*f)(std::forward(args)...); }, (Return(*)(const Class *, Arg...)) nullptr, - extra...); + std::forward(extra)...); } /// Construct a cpp_function from a class method (const, lvalue ref-qualifier) @@ -165,11 +167,11 @@ class cpp_function : public function { /// but with an added `&`. template // NOLINTNEXTLINE(google-explicit-constructor) - cpp_function(Return (Class::*f)(Arg...) const &, const Extra &...extra) { + cpp_function(Return (Class::*f)(Arg...) const &, Extra &&...extra) { initialize([f](const Class *c, Arg... args) -> Return { return (c->*f)(std::forward(args)...); }, (Return(*)(const Class *, Arg...)) nullptr, - extra...); + std::forward(extra)...); } /// Return the function name @@ -1184,12 +1186,12 @@ class module_ : public object { details on the ``Extra&& ... extra`` argument, see section :ref:`extras`. \endrst */ template - module_ &def(const char *name_, Func &&f, const Extra &...extra) { + module_ &def(const char *name_, Func &&f, Extra &&...extra) { cpp_function func(std::forward(f), name(name_), scope(*this), sibling(getattr(*this, name_, none())), - extra...); + std::forward(extra)...); // NB: allow overwriting here because cpp_function sets up a chain with the intention of // overwriting (and has already checked internally that it isn't overwriting // non-functions). @@ -1572,7 +1574,7 @@ class class_ : public detail::generic_type { PYBIND11_OBJECT(class_, generic_type, PyType_Check) template - class_(handle scope, const char *name, const Extra &...extra) { + class_(handle scope, const char *name, Extra &&...extra) { using namespace detail; // MI can only be specified via class_ template options, not constructor parameters @@ -1601,7 +1603,7 @@ class class_ : public detail::generic_type { PYBIND11_EXPAND_SIDE_EFFECTS(add_base(record)); /* Process optional arguments, if any */ - process_attributes::init(extra..., &record); + process_attributes::init(std::forward(extra)..., &record); generic_type::initialize(record); @@ -1627,65 +1629,65 @@ class class_ : public detail::generic_type { static void add_base(detail::type_record &) {} template - class_ &def(const char *name_, Func &&f, const Extra &...extra) { + class_ &def(const char *name_, Func &&f, Extra &&...extra) { cpp_function cf(method_adaptor(std::forward(f)), name(name_), is_method(*this), sibling(getattr(*this, name_, none())), - extra...); + std::forward(extra)...); add_class_method(*this, name_, cf); return *this; } template - class_ &def_static(const char *name_, Func &&f, const Extra &...extra) { + class_ &def_static(const char *name_, Func &&f, Extra &&...extra) { static_assert(!std::is_member_function_pointer::value, "def_static(...) called with a non-static member function pointer"); cpp_function cf(std::forward(f), name(name_), scope(*this), sibling(getattr(*this, name_, none())), - extra...); + std::forward(extra)...); auto cf_name = cf.name(); attr(std::move(cf_name)) = staticmethod(std::move(cf)); return *this; } template = 0> - class_ &def(const T &op, const Extra &...extra) { - op.execute(*this, extra...); + class_ &def(const T &op, Extra &&...extra) { + op.execute(*this, std::forward(extra)...); return *this; } template = 0> - class_ &def_cast(const T &op, const Extra &...extra) { - op.execute_cast(*this, extra...); + class_ &def_cast(const T &op, Extra &&...extra) { + op.execute_cast(*this, std::forward(extra)...); return *this; } template - class_ &def(const detail::initimpl::constructor &init, const Extra &...extra) { + class_ &def(const detail::initimpl::constructor &init, Extra &&...extra) { PYBIND11_WORKAROUND_INCORRECT_MSVC_C4100(init); - init.execute(*this, extra...); + init.execute(*this, std::forward(extra)...); return *this; } template - class_ &def(const detail::initimpl::alias_constructor &init, const Extra &...extra) { + class_ &def(const detail::initimpl::alias_constructor &init, Extra &&...extra) { PYBIND11_WORKAROUND_INCORRECT_MSVC_C4100(init); - init.execute(*this, extra...); + init.execute(*this, std::forward(extra)...); return *this; } template - class_ &def(detail::initimpl::factory &&init, const Extra &...extra) { - std::move(init).execute(*this, extra...); + class_ &def(detail::initimpl::factory &&init, Extra &&...extra) { + std::move(init).execute(*this, std::forward(extra)...); return *this; } template - class_ &def(detail::initimpl::pickle_factory &&pf, const Extra &...extra) { - std::move(pf).execute(*this, extra...); + class_ &def(detail::initimpl::pickle_factory &&pf, Extra &&...extra) { + std::move(pf).execute(*this, std::forward(extra)...); return *this; } @@ -1723,88 +1725,96 @@ class class_ : public detail::generic_type { } template - class_ &def_readwrite(const char *name, D C::*pm, const Extra &...extra) { + class_ &def_readwrite(const char *name, D C::*pm, Extra &&...extra) { static_assert(std::is_same::value || std::is_base_of::value, "def_readwrite() requires a class member (or base class member)"); cpp_function fget([pm](const type &c) -> const D & { return c.*pm; }, is_method(*this)), fset([pm](type &c, const D &value) { c.*pm = value; }, is_method(*this)); - def_property(name, fget, fset, return_value_policy::reference_internal, extra...); + def_property(name, + fget, + fset, + return_value_policy::reference_internal, + std::forward(extra)...); return *this; } template - class_ &def_readonly(const char *name, const D C::*pm, const Extra &...extra) { + class_ &def_readonly(const char *name, const D C::*pm, Extra &&...extra) { static_assert(std::is_same::value || std::is_base_of::value, "def_readonly() requires a class member (or base class member)"); cpp_function fget([pm](const type &c) -> const D & { return c.*pm; }, is_method(*this)); - def_property_readonly(name, fget, return_value_policy::reference_internal, extra...); + def_property_readonly( + name, fget, return_value_policy::reference_internal, std::forward(extra)...); return *this; } template - class_ &def_readwrite_static(const char *name, D *pm, const Extra &...extra) { + class_ &def_readwrite_static(const char *name, D *pm, Extra &&...extra) { cpp_function fget([pm](const object &) -> const D & { return *pm; }, scope(*this)), fset([pm](const object &, const D &value) { *pm = value; }, scope(*this)); - def_property_static(name, fget, fset, return_value_policy::reference, extra...); + def_property_static( + name, fget, fset, return_value_policy::reference, std::forward(extra)...); return *this; } template - class_ &def_readonly_static(const char *name, const D *pm, const Extra &...extra) { + class_ &def_readonly_static(const char *name, const D *pm, Extra &&...extra) { cpp_function fget([pm](const object &) -> const D & { return *pm; }, scope(*this)); - def_property_readonly_static(name, fget, return_value_policy::reference, extra...); + def_property_readonly_static( + name, fget, return_value_policy::reference, std::forward(extra)...); return *this; } /// Uses return_value_policy::reference_internal by default template - class_ &def_property_readonly(const char *name, const Getter &fget, const Extra &...extra) { + class_ &def_property_readonly(const char *name, const Getter &fget, Extra &&...extra) { return def_property_readonly(name, cpp_function(method_adaptor(fget)), return_value_policy::reference_internal, - extra...); + std::forward(extra)...); } /// Uses cpp_function's return_value_policy by default template - class_ & - def_property_readonly(const char *name, const cpp_function &fget, const Extra &...extra) { - return def_property(name, fget, nullptr, extra...); + class_ &def_property_readonly(const char *name, const cpp_function &fget, Extra &&...extra) { + return def_property(name, fget, nullptr, std::forward(extra)...); } /// Uses return_value_policy::reference by default template - class_ & - def_property_readonly_static(const char *name, const Getter &fget, const Extra &...extra) { - return def_property_readonly_static( - name, cpp_function(fget), return_value_policy::reference, extra...); + class_ &def_property_readonly_static(const char *name, const Getter &fget, Extra &&...extra) { + return def_property_readonly_static(name, + cpp_function(fget), + return_value_policy::reference, + std::forward(extra)...); } /// Uses cpp_function's return_value_policy by default template - class_ &def_property_readonly_static(const char *name, - const cpp_function &fget, - const Extra &...extra) { - return def_property_static(name, fget, nullptr, extra...); + class_ & + def_property_readonly_static(const char *name, const cpp_function &fget, Extra &&...extra) { + return def_property_static(name, fget, nullptr, std::forward(extra)...); } /// Uses return_value_policy::reference_internal by default template class_ & - def_property(const char *name, const Getter &fget, const Setter &fset, const Extra &...extra) { - return def_property( - name, fget, cpp_function(method_adaptor(fset), is_setter()), extra...); + def_property(const char *name, const Getter &fget, const Setter &fset, Extra &&...extra) { + return def_property(name, + fget, + cpp_function(method_adaptor(fset), is_setter()), + std::forward(extra)...); } template class_ &def_property(const char *name, const Getter &fget, const cpp_function &fset, - const Extra &...extra) { + Extra &&...extra) { return def_property(name, cpp_function(method_adaptor(fget)), fset, return_value_policy::reference_internal, - extra...); + std::forward(extra)...); } /// Uses cpp_function's return_value_policy by default @@ -1812,8 +1822,9 @@ class class_ : public detail::generic_type { class_ &def_property(const char *name, const cpp_function &fget, const cpp_function &fset, - const Extra &...extra) { - return def_property_static(name, fget, fset, is_method(*this), extra...); + Extra &&...extra) { + return def_property_static( + name, fget, fset, is_method(*this), std::forward(extra)...); } /// Uses return_value_policy::reference by default @@ -1821,9 +1832,12 @@ class class_ : public detail::generic_type { class_ &def_property_static(const char *name, const Getter &fget, const cpp_function &fset, - const Extra &...extra) { - return def_property_static( - name, cpp_function(fget), fset, return_value_policy::reference, extra...); + Extra &&...extra) { + return def_property_static(name, + cpp_function(fget), + fset, + return_value_policy::reference, + std::forward(extra)...); } /// Uses cpp_function's return_value_policy by default @@ -1831,7 +1845,7 @@ class class_ : public detail::generic_type { class_ &def_property_static(const char *name, const cpp_function &fget, const cpp_function &fset, - const Extra &...extra) { + Extra &&...extra) { static_assert(0 == detail::constexpr_sum(std::is_base_of::value...), "Argument annotations are not allowed for properties"); auto rec_fget = get_function_record(fget), rec_fset = get_function_record(fset); @@ -2238,8 +2252,8 @@ class enum_ : public class_ { Underlying>; template - enum_(const handle &scope, const char *name, const Extra &...extra) - : class_(scope, name, extra...), m_base(*this, scope) { + enum_(const handle &scope, const char *name, Extra &&...extra) + : class_(scope, name, std::forward(extra)...), m_base(*this, scope) { constexpr bool is_arithmetic = detail::any_of...>::value; constexpr bool is_convertible = std::is_convertible::value; m_base.init(is_arithmetic, is_convertible);