Andreas Sandberg | c79706f | 2017-02-27 13:17:51 +0000 | [diff] [blame] | 1 | /* |
| 2 | tests/test_methods_and_attributes.cpp -- constructors, deconstructors, attribute access, |
| 3 | __str__, argument and return value conventions |
| 4 | |
| 5 | Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch> |
| 6 | |
| 7 | All rights reserved. Use of this source code is governed by a |
| 8 | BSD-style license that can be found in the LICENSE file. |
| 9 | */ |
| 10 | |
| 11 | #include "pybind11_tests.h" |
| 12 | #include "constructor_stats.h" |
| 13 | |
Bobby R. Bruce | f97cf54 | 2019-09-23 13:52:58 -0700 | [diff] [blame] | 14 | #if !defined(PYBIND11_OVERLOAD_CAST) |
| 15 | template <typename... Args> |
| 16 | using overload_cast_ = pybind11::detail::overload_cast_impl<Args...>; |
| 17 | #endif |
| 18 | |
Andreas Sandberg | c79706f | 2017-02-27 13:17:51 +0000 | [diff] [blame] | 19 | class ExampleMandA { |
| 20 | public: |
| 21 | ExampleMandA() { print_default_created(this); } |
Jason Lowe-Power | 1e8aeee | 2021-11-06 13:16:21 -0700 | [diff] [blame] | 22 | explicit ExampleMandA(int value) : value(value) { print_created(this, value); } |
Andreas Sandberg | c79706f | 2017-02-27 13:17:51 +0000 | [diff] [blame] | 23 | ExampleMandA(const ExampleMandA &e) : value(e.value) { print_copy_created(this); } |
Jason Lowe-Power | 1e8aeee | 2021-11-06 13:16:21 -0700 | [diff] [blame] | 24 | explicit ExampleMandA(std::string &&) {} |
| 25 | ExampleMandA(ExampleMandA &&e) noexcept : value(e.value) { print_move_created(this); } |
Andreas Sandberg | c79706f | 2017-02-27 13:17:51 +0000 | [diff] [blame] | 26 | ~ExampleMandA() { print_destroyed(this); } |
| 27 | |
Jason Lowe-Power | 1e8aeee | 2021-11-06 13:16:21 -0700 | [diff] [blame] | 28 | std::string toString() const { return "ExampleMandA[value=" + std::to_string(value) + "]"; } |
Andreas Sandberg | c79706f | 2017-02-27 13:17:51 +0000 | [diff] [blame] | 29 | |
| 30 | void operator=(const ExampleMandA &e) { print_copy_assigned(this); value = e.value; } |
Jason Lowe-Power | 1e8aeee | 2021-11-06 13:16:21 -0700 | [diff] [blame] | 31 | void operator=(ExampleMandA &&e) noexcept { |
| 32 | print_move_assigned(this); |
| 33 | value = e.value; |
| 34 | } |
Andreas Sandberg | c79706f | 2017-02-27 13:17:51 +0000 | [diff] [blame] | 35 | |
Jason Lowe-Power | 1e8aeee | 2021-11-06 13:16:21 -0700 | [diff] [blame] | 36 | // NOLINTNEXTLINE(performance-unnecessary-value-param) |
Jason Lowe-Power | f07d506 | 2017-11-17 17:02:05 -0800 | [diff] [blame] | 37 | void add1(ExampleMandA other) { value += other.value; } // passing by value |
| 38 | void add2(ExampleMandA &other) { value += other.value; } // passing by reference |
| 39 | void add3(const ExampleMandA &other) { value += other.value; } // passing by const reference |
| 40 | void add4(ExampleMandA *other) { value += other->value; } // passing by pointer |
| 41 | void add5(const ExampleMandA *other) { value += other->value; } // passing by const pointer |
Andreas Sandberg | c79706f | 2017-02-27 13:17:51 +0000 | [diff] [blame] | 42 | |
Jason Lowe-Power | f07d506 | 2017-11-17 17:02:05 -0800 | [diff] [blame] | 43 | void add6(int other) { value += other; } // passing by value |
| 44 | void add7(int &other) { value += other; } // passing by reference |
| 45 | void add8(const int &other) { value += other; } // passing by const reference |
Jason Lowe-Power | 1e8aeee | 2021-11-06 13:16:21 -0700 | [diff] [blame] | 46 | // NOLINTNEXTLINE(readability-non-const-parameter) Deliberately non-const for testing |
Jason Lowe-Power | f07d506 | 2017-11-17 17:02:05 -0800 | [diff] [blame] | 47 | void add9(int *other) { value += *other; } // passing by pointer |
| 48 | void add10(const int *other) { value += *other; } // passing by const pointer |
Andreas Sandberg | c79706f | 2017-02-27 13:17:51 +0000 | [diff] [blame] | 49 | |
Gabe Black | c4aaf37 | 2021-01-31 06:07:28 -0800 | [diff] [blame] | 50 | void consume_str(std::string&&) {} |
| 51 | |
Jason Lowe-Power | f07d506 | 2017-11-17 17:02:05 -0800 | [diff] [blame] | 52 | ExampleMandA self1() { return *this; } // return by value |
| 53 | ExampleMandA &self2() { return *this; } // return by reference |
Jason Lowe-Power | 1e8aeee | 2021-11-06 13:16:21 -0700 | [diff] [blame] | 54 | const ExampleMandA &self3() const { return *this; } // return by const reference |
Jason Lowe-Power | f07d506 | 2017-11-17 17:02:05 -0800 | [diff] [blame] | 55 | ExampleMandA *self4() { return this; } // return by pointer |
Jason Lowe-Power | 1e8aeee | 2021-11-06 13:16:21 -0700 | [diff] [blame] | 56 | const ExampleMandA *self5() const { return this; } // return by const pointer |
Andreas Sandberg | c79706f | 2017-02-27 13:17:51 +0000 | [diff] [blame] | 57 | |
Jason Lowe-Power | 1e8aeee | 2021-11-06 13:16:21 -0700 | [diff] [blame] | 58 | int internal1() const { return value; } // return by value |
Jason Lowe-Power | f07d506 | 2017-11-17 17:02:05 -0800 | [diff] [blame] | 59 | int &internal2() { return value; } // return by reference |
Jason Lowe-Power | 1e8aeee | 2021-11-06 13:16:21 -0700 | [diff] [blame] | 60 | const int &internal3() const { return value; } // return by const reference |
Jason Lowe-Power | f07d506 | 2017-11-17 17:02:05 -0800 | [diff] [blame] | 61 | int *internal4() { return &value; } // return by pointer |
| 62 | const int *internal5() { return &value; } // return by const pointer |
Andreas Sandberg | c79706f | 2017-02-27 13:17:51 +0000 | [diff] [blame] | 63 | |
Jason Lowe-Power | f07d506 | 2017-11-17 17:02:05 -0800 | [diff] [blame] | 64 | py::str overloaded() { return "()"; } |
| 65 | py::str overloaded(int) { return "(int)"; } |
Andreas Sandberg | 6914a22 | 2017-05-09 19:22:53 +0100 | [diff] [blame] | 66 | py::str overloaded(int, float) { return "(int, float)"; } |
| 67 | py::str overloaded(float, int) { return "(float, int)"; } |
| 68 | py::str overloaded(int, int) { return "(int, int)"; } |
| 69 | py::str overloaded(float, float) { return "(float, float)"; } |
Jason Lowe-Power | f07d506 | 2017-11-17 17:02:05 -0800 | [diff] [blame] | 70 | py::str overloaded(int) const { return "(int) const"; } |
Andreas Sandberg | 6914a22 | 2017-05-09 19:22:53 +0100 | [diff] [blame] | 71 | py::str overloaded(int, float) const { return "(int, float) const"; } |
| 72 | py::str overloaded(float, int) const { return "(float, int) const"; } |
| 73 | py::str overloaded(int, int) const { return "(int, int) const"; } |
| 74 | py::str overloaded(float, float) const { return "(float, float) const"; } |
Andreas Sandberg | c79706f | 2017-02-27 13:17:51 +0000 | [diff] [blame] | 75 | |
Jason Lowe-Power | f07d506 | 2017-11-17 17:02:05 -0800 | [diff] [blame] | 76 | static py::str overloaded(float) { return "static float"; } |
| 77 | |
Andreas Sandberg | c79706f | 2017-02-27 13:17:51 +0000 | [diff] [blame] | 78 | int value = 0; |
| 79 | }; |
| 80 | |
| 81 | struct TestProperties { |
| 82 | int value = 1; |
| 83 | static int static_value; |
| 84 | |
| 85 | int get() const { return value; } |
| 86 | void set(int v) { value = v; } |
| 87 | |
| 88 | static int static_get() { return static_value; } |
| 89 | static void static_set(int v) { static_value = v; } |
| 90 | }; |
Andreas Sandberg | c79706f | 2017-02-27 13:17:51 +0000 | [diff] [blame] | 91 | int TestProperties::static_value = 1; |
| 92 | |
Jason Lowe-Power | f07d506 | 2017-11-17 17:02:05 -0800 | [diff] [blame] | 93 | struct TestPropertiesOverride : TestProperties { |
| 94 | int value = 99; |
| 95 | static int static_value; |
| 96 | }; |
| 97 | int TestPropertiesOverride::static_value = 99; |
Andreas Sandberg | c79706f | 2017-02-27 13:17:51 +0000 | [diff] [blame] | 98 | |
| 99 | struct TestPropRVP { |
Jason Lowe-Power | f07d506 | 2017-11-17 17:02:05 -0800 | [diff] [blame] | 100 | UserType v1{1}; |
| 101 | UserType v2{1}; |
| 102 | static UserType sv1; |
| 103 | static UserType sv2; |
Andreas Sandberg | c79706f | 2017-02-27 13:17:51 +0000 | [diff] [blame] | 104 | |
Jason Lowe-Power | f07d506 | 2017-11-17 17:02:05 -0800 | [diff] [blame] | 105 | const UserType &get1() const { return v1; } |
| 106 | const UserType &get2() const { return v2; } |
| 107 | UserType get_rvalue() const { return v2; } |
| 108 | void set1(int v) { v1.set(v); } |
| 109 | void set2(int v) { v2.set(v); } |
Andreas Sandberg | c79706f | 2017-02-27 13:17:51 +0000 | [diff] [blame] | 110 | }; |
Jason Lowe-Power | f07d506 | 2017-11-17 17:02:05 -0800 | [diff] [blame] | 111 | UserType TestPropRVP::sv1(1); |
| 112 | UserType TestPropRVP::sv2(1); |
Andreas Sandberg | c79706f | 2017-02-27 13:17:51 +0000 | [diff] [blame] | 113 | |
Jason Lowe-Power | f07d506 | 2017-11-17 17:02:05 -0800 | [diff] [blame] | 114 | // Test None-allowed py::arg argument policy |
| 115 | class NoneTester { public: int answer = 42; }; |
| 116 | int none1(const NoneTester &obj) { return obj.answer; } |
| 117 | int none2(NoneTester *obj) { return obj ? obj->answer : -1; } |
| 118 | int none3(std::shared_ptr<NoneTester> &obj) { return obj ? obj->answer : -1; } |
| 119 | int none4(std::shared_ptr<NoneTester> *obj) { return obj && *obj ? (*obj)->answer : -1; } |
Jason Lowe-Power | 1e8aeee | 2021-11-06 13:16:21 -0700 | [diff] [blame] | 120 | int none5(const std::shared_ptr<NoneTester> &obj) { return obj ? obj->answer : -1; } |
| 121 | |
| 122 | // Issue #2778: implicit casting from None to object (not pointer) |
| 123 | class NoneCastTester { |
| 124 | public: |
| 125 | int answer = -1; |
| 126 | NoneCastTester() = default; |
| 127 | explicit NoneCastTester(int v) : answer(v) {} |
| 128 | }; |
Jason Lowe-Power | f07d506 | 2017-11-17 17:02:05 -0800 | [diff] [blame] | 129 | |
| 130 | struct StrIssue { |
| 131 | int val = -1; |
| 132 | |
| 133 | StrIssue() = default; |
Jason Lowe-Power | 1e8aeee | 2021-11-06 13:16:21 -0700 | [diff] [blame] | 134 | explicit StrIssue(int i) : val{i} {} |
Jason Lowe-Power | f07d506 | 2017-11-17 17:02:05 -0800 | [diff] [blame] | 135 | }; |
| 136 | |
| 137 | // Issues #854, #910: incompatible function args when member function/pointer is in unregistered base class |
| 138 | class UnregisteredBase { |
| 139 | public: |
| 140 | void do_nothing() const {} |
| 141 | void increase_value() { rw_value++; ro_value += 0.25; } |
| 142 | void set_int(int v) { rw_value = v; } |
| 143 | int get_int() const { return rw_value; } |
| 144 | double get_double() const { return ro_value; } |
| 145 | int rw_value = 42; |
| 146 | double ro_value = 1.25; |
| 147 | }; |
| 148 | class RegisteredDerived : public UnregisteredBase { |
| 149 | public: |
| 150 | using UnregisteredBase::UnregisteredBase; |
| 151 | double sum() const { return rw_value + ro_value; } |
| 152 | }; |
| 153 | |
Gabe Black | c4aaf37 | 2021-01-31 06:07:28 -0800 | [diff] [blame] | 154 | // Test explicit lvalue ref-qualification |
| 155 | struct RefQualified { |
| 156 | int value = 0; |
| 157 | |
| 158 | void refQualified(int other) & { value += other; } |
| 159 | int constRefQualified(int other) const & { return value + other; } |
| 160 | }; |
| 161 | |
Jason Lowe-Power | f07d506 | 2017-11-17 17:02:05 -0800 | [diff] [blame] | 162 | TEST_SUBMODULE(methods_and_attributes, m) { |
| 163 | // test_methods_and_attributes |
| 164 | py::class_<ExampleMandA> emna(m, "ExampleMandA"); |
| 165 | emna.def(py::init<>()) |
Andreas Sandberg | c79706f | 2017-02-27 13:17:51 +0000 | [diff] [blame] | 166 | .def(py::init<int>()) |
Gabe Black | c4aaf37 | 2021-01-31 06:07:28 -0800 | [diff] [blame] | 167 | .def(py::init<std::string&&>()) |
Andreas Sandberg | c79706f | 2017-02-27 13:17:51 +0000 | [diff] [blame] | 168 | .def(py::init<const ExampleMandA&>()) |
| 169 | .def("add1", &ExampleMandA::add1) |
| 170 | .def("add2", &ExampleMandA::add2) |
| 171 | .def("add3", &ExampleMandA::add3) |
| 172 | .def("add4", &ExampleMandA::add4) |
| 173 | .def("add5", &ExampleMandA::add5) |
| 174 | .def("add6", &ExampleMandA::add6) |
| 175 | .def("add7", &ExampleMandA::add7) |
| 176 | .def("add8", &ExampleMandA::add8) |
| 177 | .def("add9", &ExampleMandA::add9) |
| 178 | .def("add10", &ExampleMandA::add10) |
Gabe Black | c4aaf37 | 2021-01-31 06:07:28 -0800 | [diff] [blame] | 179 | .def("consume_str", &ExampleMandA::consume_str) |
Andreas Sandberg | c79706f | 2017-02-27 13:17:51 +0000 | [diff] [blame] | 180 | .def("self1", &ExampleMandA::self1) |
| 181 | .def("self2", &ExampleMandA::self2) |
| 182 | .def("self3", &ExampleMandA::self3) |
| 183 | .def("self4", &ExampleMandA::self4) |
| 184 | .def("self5", &ExampleMandA::self5) |
| 185 | .def("internal1", &ExampleMandA::internal1) |
| 186 | .def("internal2", &ExampleMandA::internal2) |
| 187 | .def("internal3", &ExampleMandA::internal3) |
| 188 | .def("internal4", &ExampleMandA::internal4) |
| 189 | .def("internal5", &ExampleMandA::internal5) |
| 190 | #if defined(PYBIND11_OVERLOAD_CAST) |
Jason Lowe-Power | f07d506 | 2017-11-17 17:02:05 -0800 | [diff] [blame] | 191 | .def("overloaded", py::overload_cast<>(&ExampleMandA::overloaded)) |
| 192 | .def("overloaded", py::overload_cast<int>(&ExampleMandA::overloaded)) |
Andreas Sandberg | 6914a22 | 2017-05-09 19:22:53 +0100 | [diff] [blame] | 193 | .def("overloaded", py::overload_cast<int, float>(&ExampleMandA::overloaded)) |
| 194 | .def("overloaded", py::overload_cast<float, int>(&ExampleMandA::overloaded)) |
| 195 | .def("overloaded", py::overload_cast<int, int>(&ExampleMandA::overloaded)) |
| 196 | .def("overloaded", py::overload_cast<float, float>(&ExampleMandA::overloaded)) |
| 197 | .def("overloaded_float", py::overload_cast<float, float>(&ExampleMandA::overloaded)) |
Jason Lowe-Power | f07d506 | 2017-11-17 17:02:05 -0800 | [diff] [blame] | 198 | .def("overloaded_const", py::overload_cast<int >(&ExampleMandA::overloaded, py::const_)) |
Andreas Sandberg | 6914a22 | 2017-05-09 19:22:53 +0100 | [diff] [blame] | 199 | .def("overloaded_const", py::overload_cast<int, float>(&ExampleMandA::overloaded, py::const_)) |
| 200 | .def("overloaded_const", py::overload_cast<float, int>(&ExampleMandA::overloaded, py::const_)) |
| 201 | .def("overloaded_const", py::overload_cast<int, int>(&ExampleMandA::overloaded, py::const_)) |
| 202 | .def("overloaded_const", py::overload_cast<float, float>(&ExampleMandA::overloaded, py::const_)) |
Andreas Sandberg | c79706f | 2017-02-27 13:17:51 +0000 | [diff] [blame] | 203 | #else |
Bobby R. Bruce | f97cf54 | 2019-09-23 13:52:58 -0700 | [diff] [blame] | 204 | // Use both the traditional static_cast method and the C++11 compatible overload_cast_ |
| 205 | .def("overloaded", overload_cast_<>()(&ExampleMandA::overloaded)) |
| 206 | .def("overloaded", overload_cast_<int>()(&ExampleMandA::overloaded)) |
| 207 | .def("overloaded", overload_cast_<int, float>()(&ExampleMandA::overloaded)) |
Andreas Sandberg | 6914a22 | 2017-05-09 19:22:53 +0100 | [diff] [blame] | 208 | .def("overloaded", static_cast<py::str (ExampleMandA::*)(float, int)>(&ExampleMandA::overloaded)) |
| 209 | .def("overloaded", static_cast<py::str (ExampleMandA::*)(int, int)>(&ExampleMandA::overloaded)) |
| 210 | .def("overloaded", static_cast<py::str (ExampleMandA::*)(float, float)>(&ExampleMandA::overloaded)) |
Bobby R. Bruce | f97cf54 | 2019-09-23 13:52:58 -0700 | [diff] [blame] | 211 | .def("overloaded_float", overload_cast_<float, float>()(&ExampleMandA::overloaded)) |
| 212 | .def("overloaded_const", overload_cast_<int >()(&ExampleMandA::overloaded, py::const_)) |
| 213 | .def("overloaded_const", overload_cast_<int, float>()(&ExampleMandA::overloaded, py::const_)) |
Andreas Sandberg | 6914a22 | 2017-05-09 19:22:53 +0100 | [diff] [blame] | 214 | .def("overloaded_const", static_cast<py::str (ExampleMandA::*)(float, int) const>(&ExampleMandA::overloaded)) |
| 215 | .def("overloaded_const", static_cast<py::str (ExampleMandA::*)(int, int) const>(&ExampleMandA::overloaded)) |
| 216 | .def("overloaded_const", static_cast<py::str (ExampleMandA::*)(float, float) const>(&ExampleMandA::overloaded)) |
Andreas Sandberg | c79706f | 2017-02-27 13:17:51 +0000 | [diff] [blame] | 217 | #endif |
Jason Lowe-Power | f07d506 | 2017-11-17 17:02:05 -0800 | [diff] [blame] | 218 | // test_no_mixed_overloads |
| 219 | // Raise error if trying to mix static/non-static overloads on the same name: |
| 220 | .def_static("add_mixed_overloads1", []() { |
Gabe Black | c4aaf37 | 2021-01-31 06:07:28 -0800 | [diff] [blame] | 221 | auto emna = py::reinterpret_borrow<py::class_<ExampleMandA>>(py::module_::import("pybind11_tests.methods_and_attributes").attr("ExampleMandA")); |
Jason Lowe-Power | f07d506 | 2017-11-17 17:02:05 -0800 | [diff] [blame] | 222 | emna.def ("overload_mixed1", static_cast<py::str (ExampleMandA::*)(int, int)>(&ExampleMandA::overloaded)) |
| 223 | .def_static("overload_mixed1", static_cast<py::str ( *)(float )>(&ExampleMandA::overloaded)); |
| 224 | }) |
| 225 | .def_static("add_mixed_overloads2", []() { |
Gabe Black | c4aaf37 | 2021-01-31 06:07:28 -0800 | [diff] [blame] | 226 | auto emna = py::reinterpret_borrow<py::class_<ExampleMandA>>(py::module_::import("pybind11_tests.methods_and_attributes").attr("ExampleMandA")); |
Jason Lowe-Power | f07d506 | 2017-11-17 17:02:05 -0800 | [diff] [blame] | 227 | emna.def_static("overload_mixed2", static_cast<py::str ( *)(float )>(&ExampleMandA::overloaded)) |
| 228 | .def ("overload_mixed2", static_cast<py::str (ExampleMandA::*)(int, int)>(&ExampleMandA::overloaded)); |
| 229 | }) |
Andreas Sandberg | c79706f | 2017-02-27 13:17:51 +0000 | [diff] [blame] | 230 | .def("__str__", &ExampleMandA::toString) |
Andreas Sandberg | 6914a22 | 2017-05-09 19:22:53 +0100 | [diff] [blame] | 231 | .def_readwrite("value", &ExampleMandA::value); |
Andreas Sandberg | c79706f | 2017-02-27 13:17:51 +0000 | [diff] [blame] | 232 | |
Jason Lowe-Power | f07d506 | 2017-11-17 17:02:05 -0800 | [diff] [blame] | 233 | // test_copy_method |
| 234 | // Issue #443: can't call copied methods in Python 3 |
| 235 | emna.attr("add2b") = emna.attr("add2"); |
| 236 | |
| 237 | // test_properties, test_static_properties, test_static_cls |
Andreas Sandberg | c79706f | 2017-02-27 13:17:51 +0000 | [diff] [blame] | 238 | py::class_<TestProperties>(m, "TestProperties") |
| 239 | .def(py::init<>()) |
| 240 | .def_readonly("def_readonly", &TestProperties::value) |
| 241 | .def_readwrite("def_readwrite", &TestProperties::value) |
Jason Lowe-Power | 1e8aeee | 2021-11-06 13:16:21 -0700 | [diff] [blame] | 242 | .def_property("def_writeonly", nullptr, [](TestProperties &s, int v) { s.value = v; }) |
Bobby R. Bruce | f97cf54 | 2019-09-23 13:52:58 -0700 | [diff] [blame] | 243 | .def_property("def_property_writeonly", nullptr, &TestProperties::set) |
Andreas Sandberg | c79706f | 2017-02-27 13:17:51 +0000 | [diff] [blame] | 244 | .def_property_readonly("def_property_readonly", &TestProperties::get) |
| 245 | .def_property("def_property", &TestProperties::get, &TestProperties::set) |
Bobby R. Bruce | f97cf54 | 2019-09-23 13:52:58 -0700 | [diff] [blame] | 246 | .def_property("def_property_impossible", nullptr, nullptr) |
Andreas Sandberg | c79706f | 2017-02-27 13:17:51 +0000 | [diff] [blame] | 247 | .def_readonly_static("def_readonly_static", &TestProperties::static_value) |
| 248 | .def_readwrite_static("def_readwrite_static", &TestProperties::static_value) |
Jason Lowe-Power | 1e8aeee | 2021-11-06 13:16:21 -0700 | [diff] [blame] | 249 | .def_property_static("def_writeonly_static", |
| 250 | nullptr, |
| 251 | [](const py::object &, int v) { TestProperties::static_value = v; }) |
| 252 | .def_property_readonly_static( |
| 253 | "def_property_readonly_static", |
| 254 | [](const py::object &) { return TestProperties::static_get(); }) |
| 255 | .def_property_static( |
| 256 | "def_property_writeonly_static", |
| 257 | nullptr, |
| 258 | [](const py::object &, int v) { return TestProperties::static_set(v); }) |
| 259 | .def_property_static( |
| 260 | "def_property_static", |
| 261 | [](const py::object &) { return TestProperties::static_get(); }, |
| 262 | [](const py::object &, int v) { TestProperties::static_set(v); }) |
| 263 | .def_property_static( |
| 264 | "static_cls", |
| 265 | [](py::object cls) { return cls; }, |
| 266 | [](const py::object &cls, const py::function &f) { f(cls); }); |
Andreas Sandberg | c79706f | 2017-02-27 13:17:51 +0000 | [diff] [blame] | 267 | |
Jason Lowe-Power | f07d506 | 2017-11-17 17:02:05 -0800 | [diff] [blame] | 268 | py::class_<TestPropertiesOverride, TestProperties>(m, "TestPropertiesOverride") |
| 269 | .def(py::init<>()) |
| 270 | .def_readonly("def_readonly", &TestPropertiesOverride::value) |
| 271 | .def_readonly_static("def_readonly_static", &TestPropertiesOverride::static_value); |
Andreas Sandberg | c79706f | 2017-02-27 13:17:51 +0000 | [diff] [blame] | 272 | |
Jason Lowe-Power | 1e8aeee | 2021-11-06 13:16:21 -0700 | [diff] [blame] | 273 | auto static_get1 = [](const py::object &) -> const UserType & { return TestPropRVP::sv1; }; |
| 274 | auto static_get2 = [](const py::object &) -> const UserType & { return TestPropRVP::sv2; }; |
| 275 | auto static_set1 = [](const py::object &, int v) { TestPropRVP::sv1.set(v); }; |
| 276 | auto static_set2 = [](const py::object &, int v) { TestPropRVP::sv2.set(v); }; |
Andreas Sandberg | c79706f | 2017-02-27 13:17:51 +0000 | [diff] [blame] | 277 | auto rvp_copy = py::return_value_policy::copy; |
| 278 | |
Jason Lowe-Power | f07d506 | 2017-11-17 17:02:05 -0800 | [diff] [blame] | 279 | // test_property_return_value_policies |
Andreas Sandberg | c79706f | 2017-02-27 13:17:51 +0000 | [diff] [blame] | 280 | py::class_<TestPropRVP>(m, "TestPropRVP") |
| 281 | .def(py::init<>()) |
| 282 | .def_property_readonly("ro_ref", &TestPropRVP::get1) |
| 283 | .def_property_readonly("ro_copy", &TestPropRVP::get2, rvp_copy) |
| 284 | .def_property_readonly("ro_func", py::cpp_function(&TestPropRVP::get2, rvp_copy)) |
| 285 | .def_property("rw_ref", &TestPropRVP::get1, &TestPropRVP::set1) |
| 286 | .def_property("rw_copy", &TestPropRVP::get2, &TestPropRVP::set2, rvp_copy) |
Jason Lowe-Power | 1e8aeee | 2021-11-06 13:16:21 -0700 | [diff] [blame] | 287 | .def_property( |
| 288 | "rw_func", py::cpp_function(&TestPropRVP::get2, rvp_copy), &TestPropRVP::set2) |
Andreas Sandberg | c79706f | 2017-02-27 13:17:51 +0000 | [diff] [blame] | 289 | .def_property_readonly_static("static_ro_ref", static_get1) |
| 290 | .def_property_readonly_static("static_ro_copy", static_get2, rvp_copy) |
| 291 | .def_property_readonly_static("static_ro_func", py::cpp_function(static_get2, rvp_copy)) |
| 292 | .def_property_static("static_rw_ref", static_get1, static_set1) |
| 293 | .def_property_static("static_rw_copy", static_get2, static_set2, rvp_copy) |
Jason Lowe-Power | 1e8aeee | 2021-11-06 13:16:21 -0700 | [diff] [blame] | 294 | .def_property_static( |
| 295 | "static_rw_func", py::cpp_function(static_get2, rvp_copy), static_set2) |
Jason Lowe-Power | f07d506 | 2017-11-17 17:02:05 -0800 | [diff] [blame] | 296 | // test_property_rvalue_policy |
Andreas Sandberg | c79706f | 2017-02-27 13:17:51 +0000 | [diff] [blame] | 297 | .def_property_readonly("rvalue", &TestPropRVP::get_rvalue) |
Jason Lowe-Power | 1e8aeee | 2021-11-06 13:16:21 -0700 | [diff] [blame] | 298 | .def_property_readonly_static("static_rvalue", |
| 299 | [](const py::object &) { return UserType(1); }); |
Andreas Sandberg | c79706f | 2017-02-27 13:17:51 +0000 | [diff] [blame] | 300 | |
Jason Lowe-Power | f07d506 | 2017-11-17 17:02:05 -0800 | [diff] [blame] | 301 | // test_metaclass_override |
Andreas Sandberg | 6914a22 | 2017-05-09 19:22:53 +0100 | [diff] [blame] | 302 | struct MetaclassOverride { }; |
| 303 | py::class_<MetaclassOverride>(m, "MetaclassOverride", py::metaclass((PyObject *) &PyType_Type)) |
Jason Lowe-Power | 1e8aeee | 2021-11-06 13:16:21 -0700 | [diff] [blame] | 304 | .def_property_readonly_static("readonly", [](const py::object &) { return 1; }); |
Andreas Sandberg | 6914a22 | 2017-05-09 19:22:53 +0100 | [diff] [blame] | 305 | |
Gabe Black | c4aaf37 | 2021-01-31 06:07:28 -0800 | [diff] [blame] | 306 | // test_overload_ordering |
Jason Lowe-Power | 1e8aeee | 2021-11-06 13:16:21 -0700 | [diff] [blame] | 307 | m.def("overload_order", [](const std::string &) { return 1; }); |
| 308 | m.def("overload_order", [](const std::string &) { return 2; }); |
Gabe Black | c4aaf37 | 2021-01-31 06:07:28 -0800 | [diff] [blame] | 309 | m.def("overload_order", [](int) { return 3; }); |
| 310 | m.def("overload_order", [](int) { return 4; }, py::prepend{}); |
| 311 | |
Andreas Sandberg | 6914a22 | 2017-05-09 19:22:53 +0100 | [diff] [blame] | 312 | #if !defined(PYPY_VERSION) |
Jason Lowe-Power | f07d506 | 2017-11-17 17:02:05 -0800 | [diff] [blame] | 313 | // test_dynamic_attributes |
| 314 | class DynamicClass { |
| 315 | public: |
| 316 | DynamicClass() { print_default_created(this); } |
Gabe Black | c4aaf37 | 2021-01-31 06:07:28 -0800 | [diff] [blame] | 317 | DynamicClass(const DynamicClass&) = delete; |
Jason Lowe-Power | f07d506 | 2017-11-17 17:02:05 -0800 | [diff] [blame] | 318 | ~DynamicClass() { print_destroyed(this); } |
| 319 | }; |
Andreas Sandberg | c79706f | 2017-02-27 13:17:51 +0000 | [diff] [blame] | 320 | py::class_<DynamicClass>(m, "DynamicClass", py::dynamic_attr()) |
| 321 | .def(py::init()); |
| 322 | |
Jason Lowe-Power | f07d506 | 2017-11-17 17:02:05 -0800 | [diff] [blame] | 323 | class CppDerivedDynamicClass : public DynamicClass { }; |
Andreas Sandberg | c79706f | 2017-02-27 13:17:51 +0000 | [diff] [blame] | 324 | py::class_<CppDerivedDynamicClass, DynamicClass>(m, "CppDerivedDynamicClass") |
| 325 | .def(py::init()); |
Andreas Sandberg | 6914a22 | 2017-05-09 19:22:53 +0100 | [diff] [blame] | 326 | #endif |
| 327 | |
Jason Lowe-Power | f07d506 | 2017-11-17 17:02:05 -0800 | [diff] [blame] | 328 | // test_bad_arg_default |
| 329 | // Issue/PR #648: bad arg default debugging output |
Andreas Sandberg | 6914a22 | 2017-05-09 19:22:53 +0100 | [diff] [blame] | 330 | #if !defined(NDEBUG) |
| 331 | m.attr("debug_enabled") = true; |
| 332 | #else |
| 333 | m.attr("debug_enabled") = false; |
| 334 | #endif |
| 335 | m.def("bad_arg_def_named", []{ |
Gabe Black | c4aaf37 | 2021-01-31 06:07:28 -0800 | [diff] [blame] | 336 | auto m = py::module_::import("pybind11_tests"); |
Jason Lowe-Power | f07d506 | 2017-11-17 17:02:05 -0800 | [diff] [blame] | 337 | m.def("should_fail", [](int, UnregisteredType) {}, py::arg(), py::arg("a") = UnregisteredType()); |
Andreas Sandberg | 6914a22 | 2017-05-09 19:22:53 +0100 | [diff] [blame] | 338 | }); |
| 339 | m.def("bad_arg_def_unnamed", []{ |
Gabe Black | c4aaf37 | 2021-01-31 06:07:28 -0800 | [diff] [blame] | 340 | auto m = py::module_::import("pybind11_tests"); |
Jason Lowe-Power | f07d506 | 2017-11-17 17:02:05 -0800 | [diff] [blame] | 341 | m.def("should_fail", [](int, UnregisteredType) {}, py::arg(), py::arg() = UnregisteredType()); |
Andreas Sandberg | 6914a22 | 2017-05-09 19:22:53 +0100 | [diff] [blame] | 342 | }); |
Jason Lowe-Power | f07d506 | 2017-11-17 17:02:05 -0800 | [diff] [blame] | 343 | |
Gabe Black | c4aaf37 | 2021-01-31 06:07:28 -0800 | [diff] [blame] | 344 | // [workaround(intel)] ICC 20/21 breaks with py::arg().stuff, using py::arg{}.stuff works. |
| 345 | |
Jason Lowe-Power | f07d506 | 2017-11-17 17:02:05 -0800 | [diff] [blame] | 346 | // test_accepts_none |
| 347 | py::class_<NoneTester, std::shared_ptr<NoneTester>>(m, "NoneTester") |
| 348 | .def(py::init<>()); |
Gabe Black | c4aaf37 | 2021-01-31 06:07:28 -0800 | [diff] [blame] | 349 | m.def("no_none1", &none1, py::arg{}.none(false)); |
| 350 | m.def("no_none2", &none2, py::arg{}.none(false)); |
| 351 | m.def("no_none3", &none3, py::arg{}.none(false)); |
| 352 | m.def("no_none4", &none4, py::arg{}.none(false)); |
| 353 | m.def("no_none5", &none5, py::arg{}.none(false)); |
Jason Lowe-Power | f07d506 | 2017-11-17 17:02:05 -0800 | [diff] [blame] | 354 | m.def("ok_none1", &none1); |
Gabe Black | c4aaf37 | 2021-01-31 06:07:28 -0800 | [diff] [blame] | 355 | m.def("ok_none2", &none2, py::arg{}.none(true)); |
Jason Lowe-Power | f07d506 | 2017-11-17 17:02:05 -0800 | [diff] [blame] | 356 | m.def("ok_none3", &none3); |
Gabe Black | c4aaf37 | 2021-01-31 06:07:28 -0800 | [diff] [blame] | 357 | m.def("ok_none4", &none4, py::arg{}.none(true)); |
Jason Lowe-Power | f07d506 | 2017-11-17 17:02:05 -0800 | [diff] [blame] | 358 | m.def("ok_none5", &none5); |
| 359 | |
Gabe Black | c4aaf37 | 2021-01-31 06:07:28 -0800 | [diff] [blame] | 360 | m.def("no_none_kwarg", &none2, "a"_a.none(false)); |
| 361 | m.def("no_none_kwarg_kw_only", &none2, py::kw_only(), "a"_a.none(false)); |
| 362 | |
Jason Lowe-Power | 1e8aeee | 2021-11-06 13:16:21 -0700 | [diff] [blame] | 363 | // test_casts_none |
| 364 | // Issue #2778: implicit casting from None to object (not pointer) |
| 365 | py::class_<NoneCastTester>(m, "NoneCastTester") |
| 366 | .def(py::init<>()) |
| 367 | .def(py::init<int>()) |
| 368 | .def(py::init([](py::none const&) { return NoneCastTester{}; })); |
| 369 | py::implicitly_convertible<py::none, NoneCastTester>(); |
| 370 | m.def("ok_obj_or_none", [](NoneCastTester const& foo) { return foo.answer; }); |
| 371 | |
| 372 | |
Jason Lowe-Power | f07d506 | 2017-11-17 17:02:05 -0800 | [diff] [blame] | 373 | // test_str_issue |
| 374 | // Issue #283: __str__ called on uninitialized instance when constructor arguments invalid |
| 375 | py::class_<StrIssue>(m, "StrIssue") |
| 376 | .def(py::init<int>()) |
| 377 | .def(py::init<>()) |
| 378 | .def("__str__", [](const StrIssue &si) { |
| 379 | return "StrIssue[" + std::to_string(si.val) + "]"; } |
| 380 | ); |
| 381 | |
| 382 | // test_unregistered_base_implementations |
| 383 | // |
| 384 | // Issues #854/910: incompatible function args when member function/pointer is in unregistered |
| 385 | // base class The methods and member pointers below actually resolve to members/pointers in |
| 386 | // UnregisteredBase; before this test/fix they would be registered via lambda with a first |
| 387 | // argument of an unregistered type, and thus uncallable. |
| 388 | py::class_<RegisteredDerived>(m, "RegisteredDerived") |
| 389 | .def(py::init<>()) |
| 390 | .def("do_nothing", &RegisteredDerived::do_nothing) |
| 391 | .def("increase_value", &RegisteredDerived::increase_value) |
| 392 | .def_readwrite("rw_value", &RegisteredDerived::rw_value) |
| 393 | .def_readonly("ro_value", &RegisteredDerived::ro_value) |
Jason Lowe-Power | 1e8aeee | 2021-11-06 13:16:21 -0700 | [diff] [blame] | 394 | // Uncommenting the next line should trigger a static_assert: |
| 395 | // .def_readwrite("fails", &UserType::value) |
| 396 | // Uncommenting the next line should trigger a static_assert: |
| 397 | // .def_readonly("fails", &UserType::value) |
Jason Lowe-Power | f07d506 | 2017-11-17 17:02:05 -0800 | [diff] [blame] | 398 | .def_property("rw_value_prop", &RegisteredDerived::get_int, &RegisteredDerived::set_int) |
| 399 | .def_property_readonly("ro_value_prop", &RegisteredDerived::get_double) |
| 400 | // This one is in the registered class: |
Jason Lowe-Power | 1e8aeee | 2021-11-06 13:16:21 -0700 | [diff] [blame] | 401 | .def("sum", &RegisteredDerived::sum); |
Jason Lowe-Power | f07d506 | 2017-11-17 17:02:05 -0800 | [diff] [blame] | 402 | |
| 403 | using Adapted = decltype(py::method_adaptor<RegisteredDerived>(&RegisteredDerived::do_nothing)); |
| 404 | static_assert(std::is_same<Adapted, void (RegisteredDerived::*)() const>::value, ""); |
| 405 | |
Gabe Black | c4aaf37 | 2021-01-31 06:07:28 -0800 | [diff] [blame] | 406 | // test_methods_and_attributes |
| 407 | py::class_<RefQualified>(m, "RefQualified") |
| 408 | .def(py::init<>()) |
| 409 | .def_readonly("value", &RefQualified::value) |
| 410 | .def("refQualified", &RefQualified::refQualified) |
| 411 | .def("constRefQualified", &RefQualified::constRefQualified); |
Jason Lowe-Power | f07d506 | 2017-11-17 17:02:05 -0800 | [diff] [blame] | 412 | } |