mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-22 21:25:13 +00:00
Add lvalue ref-qualified cpp_function constructors (#2213)
* added overload for l-value ref-qualified methods * Added test. Before, the code would have failed to build.
This commit is contained in:
parent
b524008967
commit
63df87fa49
@ -72,20 +72,38 @@ public:
|
|||||||
(detail::function_signature_t<Func> *) nullptr, extra...);
|
(detail::function_signature_t<Func> *) nullptr, extra...);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Construct a cpp_function from a class method (non-const)
|
/// Construct a cpp_function from a class method (non-const, no ref-qualifier)
|
||||||
template <typename Return, typename Class, typename... Arg, typename... Extra>
|
template <typename Return, typename Class, typename... Arg, typename... Extra>
|
||||||
cpp_function(Return (Class::*f)(Arg...), const Extra&... extra) {
|
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)(args...); },
|
||||||
(Return (*) (Class *, Arg...)) nullptr, extra...);
|
(Return (*) (Class *, Arg...)) nullptr, extra...);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Construct a cpp_function from a class method (const)
|
/// Construct a cpp_function from a class method (non-const, lvalue ref-qualifier)
|
||||||
|
/// A copy of the overload for non-const functions without explicit ref-qualifier
|
||||||
|
/// but with an added `&`.
|
||||||
|
template <typename Return, typename Class, typename... Arg, typename... Extra>
|
||||||
|
cpp_function(Return (Class::*f)(Arg...)&, const Extra&... extra) {
|
||||||
|
initialize([f](Class *c, Arg... args) -> Return { return (c->*f)(args...); },
|
||||||
|
(Return (*) (Class *, Arg...)) nullptr, extra...);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct a cpp_function from a class method (const, no ref-qualifier)
|
||||||
template <typename Return, typename Class, typename... Arg, typename... Extra>
|
template <typename Return, typename Class, typename... Arg, typename... Extra>
|
||||||
cpp_function(Return (Class::*f)(Arg...) const, const Extra&... extra) {
|
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)(args...); },
|
||||||
(Return (*)(const Class *, Arg ...)) nullptr, extra...);
|
(Return (*)(const Class *, Arg ...)) nullptr, extra...);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Construct a cpp_function from a class method (const, lvalue ref-qualifier)
|
||||||
|
/// A copy of the overload for const functions without explicit ref-qualifier
|
||||||
|
/// but with an added `&`.
|
||||||
|
template <typename Return, typename Class, typename... Arg, typename... Extra>
|
||||||
|
cpp_function(Return (Class::*f)(Arg...) const&, const Extra&... extra) {
|
||||||
|
initialize([f](const Class *c, Arg... args) -> Return { return (c->*f)(args...); },
|
||||||
|
(Return (*)(const Class *, Arg ...)) nullptr, extra...);
|
||||||
|
}
|
||||||
|
|
||||||
/// Return the function name
|
/// Return the function name
|
||||||
object name() const { return attr("__name__"); }
|
object name() const { return attr("__name__"); }
|
||||||
|
|
||||||
|
@ -207,6 +207,14 @@ public:
|
|||||||
double sum() const { return rw_value + ro_value; }
|
double sum() const { return rw_value + ro_value; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Test explicit lvalue ref-qualification
|
||||||
|
struct RefQualified {
|
||||||
|
int value = 0;
|
||||||
|
|
||||||
|
void refQualified(int other) & { value += other; }
|
||||||
|
int constRefQualified(int other) const & { return value + other; }
|
||||||
|
};
|
||||||
|
|
||||||
TEST_SUBMODULE(methods_and_attributes, m) {
|
TEST_SUBMODULE(methods_and_attributes, m) {
|
||||||
// test_methods_and_attributes
|
// test_methods_and_attributes
|
||||||
py::class_<ExampleMandA> emna(m, "ExampleMandA");
|
py::class_<ExampleMandA> emna(m, "ExampleMandA");
|
||||||
@ -457,4 +465,11 @@ TEST_SUBMODULE(methods_and_attributes, m) {
|
|||||||
m.def("custom_caster_destroy_const", []() -> const DestructionTester * { return new DestructionTester(); },
|
m.def("custom_caster_destroy_const", []() -> const DestructionTester * { return new DestructionTester(); },
|
||||||
py::return_value_policy::take_ownership); // Likewise (const doesn't inhibit destruction)
|
py::return_value_policy::take_ownership); // Likewise (const doesn't inhibit destruction)
|
||||||
m.def("destruction_tester_cstats", &ConstructorStats::get<DestructionTester>, py::return_value_policy::reference);
|
m.def("destruction_tester_cstats", &ConstructorStats::get<DestructionTester>, py::return_value_policy::reference);
|
||||||
|
|
||||||
|
// test_methods_and_attributes
|
||||||
|
py::class_<RefQualified>(m, "RefQualified")
|
||||||
|
.def(py::init<>())
|
||||||
|
.def_readonly("value", &RefQualified::value)
|
||||||
|
.def("refQualified", &RefQualified::refQualified)
|
||||||
|
.def("constRefQualified", &RefQualified::constRefQualified);
|
||||||
}
|
}
|
||||||
|
@ -510,3 +510,14 @@ def test_custom_caster_destruction():
|
|||||||
|
|
||||||
# Make sure we still only have the original object (from ..._no_destroy()) alive:
|
# Make sure we still only have the original object (from ..._no_destroy()) alive:
|
||||||
assert cstats.alive() == 1
|
assert cstats.alive() == 1
|
||||||
|
|
||||||
|
|
||||||
|
def test_ref_qualified():
|
||||||
|
"""Tests that explicit lvalue ref-qualified methods can be called just like their
|
||||||
|
non ref-qualified counterparts."""
|
||||||
|
|
||||||
|
r = m.RefQualified()
|
||||||
|
assert r.value == 0
|
||||||
|
r.refQualified(17)
|
||||||
|
assert r.value == 17
|
||||||
|
assert r.constRefQualified(23) == 40
|
||||||
|
Loading…
Reference in New Issue
Block a user