diff --git a/include/pybind11/pybind11.h b/include/pybind11/pybind11.h index 752f77564..83abe51fb 100644 --- a/include/pybind11/pybind11.h +++ b/include/pybind11/pybind11.h @@ -44,12 +44,12 @@ public: /// Construct a cpp_function from a vanilla function pointer template - explicit cpp_function(Return (*f)(Args...), const Extra&... extra) { + cpp_function(Return (*f)(Args...), const Extra&... extra) { initialize(f, f, extra...); } /// Construct a cpp_function from a lambda function (possibly with internal state) - template explicit cpp_function(Func &&f, const Extra&... extra) { + template cpp_function(Func &&f, const Extra&... extra) { initialize(std::forward(f), (typename detail::remove_class::type::operator())>::type *) nullptr, extra...); @@ -57,14 +57,14 @@ public: /// Construct a cpp_function from a class method (non-const) template - explicit 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...); }, (Return (*) (Class *, Arg...)) nullptr, extra...); } /// Construct a cpp_function from a class method (const) template - explicit 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...); }, (Return (*)(const Class *, Arg ...)) nullptr, extra...); } diff --git a/tests/test_methods_and_attributes.cpp b/tests/test_methods_and_attributes.cpp index c78e64b56..82c81f724 100644 --- a/tests/test_methods_and_attributes.cpp +++ b/tests/test_methods_and_attributes.cpp @@ -53,6 +53,19 @@ public: int value = 0; }; +struct TestProperties { + int value = 1; + static int static_value; + + int get() const { return value; } + void set(int v) { value = v; } + + static int static_get() { return static_value; } + static void static_set(int v) { static_value = v; } +}; + +int TestProperties::static_value = 1; + class DynamicClass { public: DynamicClass() { print_default_created(this); } @@ -90,6 +103,20 @@ test_initializer methods_and_attributes([](py::module &m) { .def_readwrite("value", &ExampleMandA::value) ; + py::class_(m, "TestProperties") + .def(py::init<>()) + .def_readonly("def_readonly", &TestProperties::value) + .def_readwrite("def_readwrite", &TestProperties::value) + .def_property_readonly("def_property_readonly", &TestProperties::get) + .def_property("def_property", &TestProperties::get, &TestProperties::set) + .def_readonly_static("def_readonly_static", &TestProperties::static_value) + .def_readwrite_static("def_readwrite_static", &TestProperties::static_value) + .def_property_readonly_static("def_property_readonly_static", + [](py::object) { return TestProperties::static_get(); }) + .def_property_static("def_property_static", + [](py::object) { return TestProperties::static_get(); }, + [](py::object, int v) { return TestProperties::static_set(v); }); + py::class_(m, "DynamicClass", py::dynamic_attr()) .def(py::init()); diff --git a/tests/test_methods_and_attributes.py b/tests/test_methods_and_attributes.py index 1c7b3daa0..f4116c3b6 100644 --- a/tests/test_methods_and_attributes.py +++ b/tests/test_methods_and_attributes.py @@ -47,6 +47,44 @@ def test_methods_and_attributes(): assert cstats.move_assignments == 0 +def test_properties(): + from pybind11_tests import TestProperties + + instance = TestProperties() + + assert instance.def_readonly == 1 + with pytest.raises(AttributeError): + instance.def_readonly = 2 + + instance.def_readwrite = 2 + assert instance.def_readwrite == 2 + + assert instance.def_property_readonly == 2 + with pytest.raises(AttributeError): + instance.def_property_readonly = 3 + + instance.def_property = 3 + assert instance.def_property == 3 + + +def test_static_properties(): + from pybind11_tests import TestProperties as Type + + assert Type.def_readonly_static == 1 + with pytest.raises(AttributeError): + Type.def_readonly_static = 2 + + Type.def_readwrite_static = 2 + assert Type.def_readwrite_static == 2 + + assert Type.def_property_readonly_static == 2 + with pytest.raises(AttributeError): + Type.def_property_readonly_static = 3 + + Type.def_property_static = 3 + assert Type.def_property_static == 3 + + def test_dynamic_attributes(): from pybind11_tests import DynamicClass, CppDerivedDynamicClass