From f2226aefe0f679c61e6eaf5d6f315796fc28cebc Mon Sep 17 00:00:00 2001 From: Robert Haschke Date: Tue, 7 Jul 2020 15:56:07 +0200 Subject: [PATCH] Allow perfect forwarding of method args (#2048) --- include/pybind11/pybind11.h | 4 ++-- tests/test_methods_and_attributes.cpp | 5 +++++ tests/test_methods_and_attributes.py | 4 ++-- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/include/pybind11/pybind11.h b/include/pybind11/pybind11.h index 7a6e56302..45828dba8 100644 --- a/include/pybind11/pybind11.h +++ b/include/pybind11/pybind11.h @@ -75,7 +75,7 @@ public: /// Construct a cpp_function from a class method (non-const, no ref-qualifier) template cpp_function(Return (Class::*f)(Arg...), const Extra&... extra) { - initialize([f](Class *c, Arg... args) -> Return { return (c->*f)(args...); }, + initialize([f](Class *c, Arg... args) -> Return { return (c->*f)(std::forward(args)...); }, (Return (*) (Class *, Arg...)) nullptr, extra...); } @@ -91,7 +91,7 @@ public: /// Construct a cpp_function from a class method (const, no ref-qualifier) template cpp_function(Return (Class::*f)(Arg...) const, const Extra&... extra) { - initialize([f](const Class *c, Arg... args) -> Return { return (c->*f)(args...); }, + initialize([f](const Class *c, Arg... args) -> Return { return (c->*f)(std::forward(args)...); }, (Return (*)(const Class *, Arg ...)) nullptr, extra...); } diff --git a/tests/test_methods_and_attributes.cpp b/tests/test_methods_and_attributes.cpp index fd95a0130..901f2046c 100644 --- a/tests/test_methods_and_attributes.cpp +++ b/tests/test_methods_and_attributes.cpp @@ -21,6 +21,7 @@ public: ExampleMandA() { print_default_created(this); } ExampleMandA(int value) : value(value) { print_created(this, value); } ExampleMandA(const ExampleMandA &e) : value(e.value) { print_copy_created(this); } + ExampleMandA(std::string&&) {} ExampleMandA(ExampleMandA &&e) : value(e.value) { print_move_created(this); } ~ExampleMandA() { print_destroyed(this); } @@ -43,6 +44,8 @@ public: void add9(int *other) { value += *other; } // passing by pointer void add10(const int *other) { value += *other; } // passing by const pointer + void consume_str(std::string&&) {} + ExampleMandA self1() { return *this; } // return by value ExampleMandA &self2() { return *this; } // return by reference const ExampleMandA &self3() { return *this; } // return by const reference @@ -150,6 +153,7 @@ TEST_SUBMODULE(methods_and_attributes, m) { py::class_ emna(m, "ExampleMandA"); emna.def(py::init<>()) .def(py::init()) + .def(py::init()) .def(py::init()) .def("add1", &ExampleMandA::add1) .def("add2", &ExampleMandA::add2) @@ -161,6 +165,7 @@ TEST_SUBMODULE(methods_and_attributes, m) { .def("add8", &ExampleMandA::add8) .def("add9", &ExampleMandA::add9) .def("add10", &ExampleMandA::add10) + .def("consume_str", &ExampleMandA::consume_str) .def("self1", &ExampleMandA::self1) .def("self2", &ExampleMandA::self2) .def("self3", &ExampleMandA::self3) diff --git a/tests/test_methods_and_attributes.py b/tests/test_methods_and_attributes.py index d1248dcf1..8bda7a8b2 100644 --- a/tests/test_methods_and_attributes.py +++ b/tests/test_methods_and_attributes.py @@ -58,8 +58,8 @@ def test_methods_and_attributes(): assert cstats.alive() == 0 assert cstats.values() == ["32"] assert cstats.default_constructions == 1 - assert cstats.copy_constructions == 3 - assert cstats.move_constructions >= 1 + assert cstats.copy_constructions == 2 + assert cstats.move_constructions >= 2 assert cstats.copy_assignments == 0 assert cstats.move_assignments == 0