test_factory_constructors.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. /*
  2. tests/test_factory_constructors.cpp -- tests construction from a factory function
  3. via py::init_factory()
  4. Copyright (c) 2017 Jason Rhinelander <[email protected]>
  5. All rights reserved. Use of this source code is governed by a
  6. BSD-style license that can be found in the LICENSE file.
  7. */
  8. #include "pybind11_tests.h"
  9. #include "constructor_stats.h"
  10. #include <cmath>
  11. #include <new>
  12. // Classes for testing python construction via C++ factory function:
  13. // Not publicly constructible, copyable, or movable:
  14. class TestFactory1 {
  15. friend class TestFactoryHelper;
  16. TestFactory1() : value("(empty)") { print_default_created(this); }
  17. TestFactory1(int v) : value(std::to_string(v)) { print_created(this, value); }
  18. TestFactory1(std::string v) : value(std::move(v)) { print_created(this, value); }
  19. TestFactory1(TestFactory1 &&) = delete;
  20. TestFactory1(const TestFactory1 &) = delete;
  21. TestFactory1 &operator=(TestFactory1 &&) = delete;
  22. TestFactory1 &operator=(const TestFactory1 &) = delete;
  23. public:
  24. std::string value;
  25. ~TestFactory1() { print_destroyed(this); }
  26. };
  27. // Non-public construction, but moveable:
  28. class TestFactory2 {
  29. friend class TestFactoryHelper;
  30. TestFactory2() : value("(empty2)") { print_default_created(this); }
  31. TestFactory2(int v) : value(std::to_string(v)) { print_created(this, value); }
  32. TestFactory2(std::string v) : value(std::move(v)) { print_created(this, value); }
  33. public:
  34. TestFactory2(TestFactory2 &&m) { value = std::move(m.value); print_move_created(this); }
  35. TestFactory2 &operator=(TestFactory2 &&m) { value = std::move(m.value); print_move_assigned(this); return *this; }
  36. std::string value;
  37. ~TestFactory2() { print_destroyed(this); }
  38. };
  39. // Mixed direct/factory construction:
  40. class TestFactory3 {
  41. protected:
  42. friend class TestFactoryHelper;
  43. TestFactory3() : value("(empty3)") { print_default_created(this); }
  44. TestFactory3(int v) : value(std::to_string(v)) { print_created(this, value); }
  45. public:
  46. TestFactory3(std::string v) : value(std::move(v)) { print_created(this, value); }
  47. TestFactory3(TestFactory3 &&m) { value = std::move(m.value); print_move_created(this); }
  48. TestFactory3 &operator=(TestFactory3 &&m) { value = std::move(m.value); print_move_assigned(this); return *this; }
  49. std::string value;
  50. virtual ~TestFactory3() { print_destroyed(this); }
  51. };
  52. // Inheritance test
  53. class TestFactory4 : public TestFactory3 {
  54. public:
  55. TestFactory4() : TestFactory3() { print_default_created(this); }
  56. TestFactory4(int v) : TestFactory3(v) { print_created(this, v); }
  57. ~TestFactory4() override { print_destroyed(this); }
  58. };
  59. // Another class for an invalid downcast test
  60. class TestFactory5 : public TestFactory3 {
  61. public:
  62. TestFactory5(int i) : TestFactory3(i) { print_created(this, i); }
  63. ~TestFactory5() override { print_destroyed(this); }
  64. };
  65. class TestFactory6 {
  66. protected:
  67. int value;
  68. bool alias = false;
  69. public:
  70. TestFactory6(int i) : value{i} { print_created(this, i); }
  71. TestFactory6(TestFactory6 &&f) { print_move_created(this); value = f.value; alias = f.alias; }
  72. TestFactory6(const TestFactory6 &f) { print_copy_created(this); value = f.value; alias = f.alias; }
  73. virtual ~TestFactory6() { print_destroyed(this); }
  74. virtual int get() { return value; }
  75. bool has_alias() { return alias; }
  76. };
  77. class PyTF6 : public TestFactory6 {
  78. public:
  79. // Special constructor that allows the factory to construct a PyTF6 from a TestFactory6 only
  80. // when an alias is needed:
  81. PyTF6(TestFactory6 &&base) : TestFactory6(std::move(base)) { alias = true; print_created(this, "move", value); }
  82. PyTF6(int i) : TestFactory6(i) { alias = true; print_created(this, i); }
  83. PyTF6(PyTF6 &&f) : TestFactory6(std::move(f)) { print_move_created(this); }
  84. PyTF6(const PyTF6 &f) : TestFactory6(f) { print_copy_created(this); }
  85. PyTF6(std::string s) : TestFactory6((int) s.size()) { alias = true; print_created(this, s); }
  86. ~PyTF6() override { print_destroyed(this); }
  87. int get() override { PYBIND11_OVERRIDE(int, TestFactory6, get, /*no args*/); }
  88. };
  89. class TestFactory7 {
  90. protected:
  91. int value;
  92. bool alias = false;
  93. public:
  94. TestFactory7(int i) : value{i} { print_created(this, i); }
  95. TestFactory7(TestFactory7 &&f) { print_move_created(this); value = f.value; alias = f.alias; }
  96. TestFactory7(const TestFactory7 &f) { print_copy_created(this); value = f.value; alias = f.alias; }
  97. virtual ~TestFactory7() { print_destroyed(this); }
  98. virtual int get() { return value; }
  99. bool has_alias() { return alias; }
  100. };
  101. class PyTF7 : public TestFactory7 {
  102. public:
  103. PyTF7(int i) : TestFactory7(i) { alias = true; print_created(this, i); }
  104. PyTF7(PyTF7 &&f) : TestFactory7(std::move(f)) { print_move_created(this); }
  105. PyTF7(const PyTF7 &f) : TestFactory7(f) { print_copy_created(this); }
  106. ~PyTF7() override { print_destroyed(this); }
  107. int get() override { PYBIND11_OVERRIDE(int, TestFactory7, get, /*no args*/); }
  108. };
  109. class TestFactoryHelper {
  110. public:
  111. // Non-movable, non-copyable type:
  112. // Return via pointer:
  113. static TestFactory1 *construct1() { return new TestFactory1(); }
  114. // Holder:
  115. static std::unique_ptr<TestFactory1> construct1(int a) { return std::unique_ptr<TestFactory1>(new TestFactory1(a)); }
  116. // pointer again
  117. static TestFactory1 *construct1_string(std::string a) { return new TestFactory1(a); }
  118. // Moveable type:
  119. // pointer:
  120. static TestFactory2 *construct2() { return new TestFactory2(); }
  121. // holder:
  122. static std::unique_ptr<TestFactory2> construct2(int a) { return std::unique_ptr<TestFactory2>(new TestFactory2(a)); }
  123. // by value moving:
  124. static TestFactory2 construct2(std::string a) { return TestFactory2(a); }
  125. // shared_ptr holder type:
  126. // pointer:
  127. static TestFactory3 *construct3() { return new TestFactory3(); }
  128. // holder:
  129. static std::shared_ptr<TestFactory3> construct3(int a) { return std::shared_ptr<TestFactory3>(new TestFactory3(a)); }
  130. };
  131. TEST_SUBMODULE(factory_constructors, m) {
  132. // Define various trivial types to allow simpler overload resolution:
  133. py::module_ m_tag = m.def_submodule("tag");
  134. #define MAKE_TAG_TYPE(Name) \
  135. struct Name##_tag {}; \
  136. py::class_<Name##_tag>(m_tag, #Name "_tag").def(py::init<>()); \
  137. m_tag.attr(#Name) = py::cast(Name##_tag{})
  138. MAKE_TAG_TYPE(pointer);
  139. MAKE_TAG_TYPE(unique_ptr);
  140. MAKE_TAG_TYPE(move);
  141. MAKE_TAG_TYPE(shared_ptr);
  142. MAKE_TAG_TYPE(derived);
  143. MAKE_TAG_TYPE(TF4);
  144. MAKE_TAG_TYPE(TF5);
  145. MAKE_TAG_TYPE(null_ptr);
  146. MAKE_TAG_TYPE(null_unique_ptr);
  147. MAKE_TAG_TYPE(null_shared_ptr);
  148. MAKE_TAG_TYPE(base);
  149. MAKE_TAG_TYPE(invalid_base);
  150. MAKE_TAG_TYPE(alias);
  151. MAKE_TAG_TYPE(unaliasable);
  152. MAKE_TAG_TYPE(mixed);
  153. // test_init_factory_basic, test_bad_type
  154. py::class_<TestFactory1>(m, "TestFactory1")
  155. .def(py::init([](unique_ptr_tag, int v) { return TestFactoryHelper::construct1(v); }))
  156. .def(py::init(&TestFactoryHelper::construct1_string)) // raw function pointer
  157. .def(py::init([](pointer_tag) { return TestFactoryHelper::construct1(); }))
  158. .def(py::init([](py::handle, int v, py::handle) { return TestFactoryHelper::construct1(v); }))
  159. .def_readwrite("value", &TestFactory1::value)
  160. ;
  161. py::class_<TestFactory2>(m, "TestFactory2")
  162. .def(py::init([](pointer_tag, int v) { return TestFactoryHelper::construct2(v); }))
  163. .def(py::init([](unique_ptr_tag, std::string v) { return TestFactoryHelper::construct2(v); }))
  164. .def(py::init([](move_tag) { return TestFactoryHelper::construct2(); }))
  165. .def_readwrite("value", &TestFactory2::value)
  166. ;
  167. // Stateful & reused:
  168. int c = 1;
  169. auto c4a = [c](pointer_tag, TF4_tag, int a) { (void) c; return new TestFactory4(a);};
  170. // test_init_factory_basic, test_init_factory_casting
  171. py::class_<TestFactory3, std::shared_ptr<TestFactory3>> pyTestFactory3(m, "TestFactory3");
  172. pyTestFactory3
  173. .def(py::init([](pointer_tag, int v) { return TestFactoryHelper::construct3(v); }))
  174. .def(py::init([](shared_ptr_tag) { return TestFactoryHelper::construct3(); }));
  175. ignoreOldStyleInitWarnings([&pyTestFactory3]() {
  176. pyTestFactory3.def("__init__", [](TestFactory3 &self, std::string v) { new (&self) TestFactory3(v); }); // placement-new ctor
  177. });
  178. pyTestFactory3
  179. // factories returning a derived type:
  180. .def(py::init(c4a)) // derived ptr
  181. .def(py::init([](pointer_tag, TF5_tag, int a) { return new TestFactory5(a); }))
  182. // derived shared ptr:
  183. .def(py::init([](shared_ptr_tag, TF4_tag, int a) { return std::make_shared<TestFactory4>(a); }))
  184. .def(py::init([](shared_ptr_tag, TF5_tag, int a) { return std::make_shared<TestFactory5>(a); }))
  185. // Returns nullptr:
  186. .def(py::init([](null_ptr_tag) { return (TestFactory3 *) nullptr; }))
  187. .def(py::init([](null_unique_ptr_tag) { return std::unique_ptr<TestFactory3>(); }))
  188. .def(py::init([](null_shared_ptr_tag) { return std::shared_ptr<TestFactory3>(); }))
  189. .def_readwrite("value", &TestFactory3::value)
  190. ;
  191. // test_init_factory_casting
  192. py::class_<TestFactory4, TestFactory3, std::shared_ptr<TestFactory4>>(m, "TestFactory4")
  193. .def(py::init(c4a)) // pointer
  194. ;
  195. // Doesn't need to be registered, but registering makes getting ConstructorStats easier:
  196. py::class_<TestFactory5, TestFactory3, std::shared_ptr<TestFactory5>>(m, "TestFactory5");
  197. // test_init_factory_alias
  198. // Alias testing
  199. py::class_<TestFactory6, PyTF6>(m, "TestFactory6")
  200. .def(py::init([](base_tag, int i) { return TestFactory6(i); }))
  201. .def(py::init([](alias_tag, int i) { return PyTF6(i); }))
  202. .def(py::init([](alias_tag, std::string s) { return PyTF6(s); }))
  203. .def(py::init([](alias_tag, pointer_tag, int i) { return new PyTF6(i); }))
  204. .def(py::init([](base_tag, pointer_tag, int i) { return new TestFactory6(i); }))
  205. .def(py::init([](base_tag, alias_tag, pointer_tag, int i) { return (TestFactory6 *) new PyTF6(i); }))
  206. .def("get", &TestFactory6::get)
  207. .def("has_alias", &TestFactory6::has_alias)
  208. .def_static("get_cstats", &ConstructorStats::get<TestFactory6>, py::return_value_policy::reference)
  209. .def_static("get_alias_cstats", &ConstructorStats::get<PyTF6>, py::return_value_policy::reference)
  210. ;
  211. // test_init_factory_dual
  212. // Separate alias constructor testing
  213. py::class_<TestFactory7, PyTF7, std::shared_ptr<TestFactory7>>(m, "TestFactory7")
  214. .def(py::init(
  215. [](int i) { return TestFactory7(i); },
  216. [](int i) { return PyTF7(i); }))
  217. .def(py::init(
  218. [](pointer_tag, int i) { return new TestFactory7(i); },
  219. [](pointer_tag, int i) { return new PyTF7(i); }))
  220. .def(py::init(
  221. [](mixed_tag, int i) { return new TestFactory7(i); },
  222. [](mixed_tag, int i) { return PyTF7(i); }))
  223. .def(py::init(
  224. [](mixed_tag, std::string s) { return TestFactory7((int) s.size()); },
  225. [](mixed_tag, std::string s) { return new PyTF7((int) s.size()); }))
  226. .def(py::init(
  227. [](base_tag, pointer_tag, int i) { return new TestFactory7(i); },
  228. [](base_tag, pointer_tag, int i) { return (TestFactory7 *) new PyTF7(i); }))
  229. .def(py::init(
  230. [](alias_tag, pointer_tag, int i) { return new PyTF7(i); },
  231. [](alias_tag, pointer_tag, int i) { return new PyTF7(10*i); }))
  232. .def(py::init(
  233. [](shared_ptr_tag, base_tag, int i) { return std::make_shared<TestFactory7>(i); },
  234. [](shared_ptr_tag, base_tag, int i) { auto *p = new PyTF7(i); return std::shared_ptr<TestFactory7>(p); }))
  235. .def(py::init(
  236. [](shared_ptr_tag, invalid_base_tag, int i) { return std::make_shared<TestFactory7>(i); },
  237. [](shared_ptr_tag, invalid_base_tag, int i) { return std::make_shared<TestFactory7>(i); })) // <-- invalid alias factory
  238. .def("get", &TestFactory7::get)
  239. .def("has_alias", &TestFactory7::has_alias)
  240. .def_static("get_cstats", &ConstructorStats::get<TestFactory7>, py::return_value_policy::reference)
  241. .def_static("get_alias_cstats", &ConstructorStats::get<PyTF7>, py::return_value_policy::reference)
  242. ;
  243. // test_placement_new_alternative
  244. // Class with a custom new operator but *without* a placement new operator (issue #948)
  245. class NoPlacementNew {
  246. public:
  247. NoPlacementNew(int i) : i(i) { }
  248. static void *operator new(std::size_t s) {
  249. auto *p = ::operator new(s);
  250. py::print("operator new called, returning", reinterpret_cast<uintptr_t>(p));
  251. return p;
  252. }
  253. static void operator delete(void *p) {
  254. py::print("operator delete called on", reinterpret_cast<uintptr_t>(p));
  255. ::operator delete(p);
  256. }
  257. int i;
  258. };
  259. // As of 2.2, `py::init<args>` no longer requires placement new
  260. py::class_<NoPlacementNew>(m, "NoPlacementNew")
  261. .def(py::init<int>())
  262. .def(py::init([]() { return new NoPlacementNew(100); }))
  263. .def_readwrite("i", &NoPlacementNew::i)
  264. ;
  265. // test_reallocations
  266. // Class that has verbose operator_new/operator_delete calls
  267. struct NoisyAlloc {
  268. NoisyAlloc(const NoisyAlloc &) = default;
  269. NoisyAlloc(int i) { py::print(py::str("NoisyAlloc(int {})").format(i)); }
  270. NoisyAlloc(double d) { py::print(py::str("NoisyAlloc(double {})").format(d)); }
  271. ~NoisyAlloc() { py::print("~NoisyAlloc()"); }
  272. static void *operator new(size_t s) { py::print("noisy new"); return ::operator new(s); }
  273. static void *operator new(size_t, void *p) { py::print("noisy placement new"); return p; }
  274. static void operator delete(void *p, size_t) { py::print("noisy delete"); ::operator delete(p); }
  275. static void operator delete(void *, void *) { py::print("noisy placement delete"); }
  276. #if defined(_MSC_VER) && _MSC_VER < 1910
  277. // MSVC 2015 bug: the above "noisy delete" isn't invoked (fixed in MSVC 2017)
  278. static void operator delete(void *p) { py::print("noisy delete"); ::operator delete(p); }
  279. #endif
  280. };
  281. py::class_<NoisyAlloc> pyNoisyAlloc(m, "NoisyAlloc");
  282. // Since these overloads have the same number of arguments, the dispatcher will try each of
  283. // them until the arguments convert. Thus we can get a pre-allocation here when passing a
  284. // single non-integer:
  285. ignoreOldStyleInitWarnings([&pyNoisyAlloc]() {
  286. pyNoisyAlloc.def("__init__", [](NoisyAlloc *a, int i) { new (a) NoisyAlloc(i); }); // Regular constructor, runs first, requires preallocation
  287. });
  288. pyNoisyAlloc.def(py::init([](double d) { return new NoisyAlloc(d); }));
  289. // The two-argument version: first the factory pointer overload.
  290. pyNoisyAlloc.def(py::init([](int i, int) { return new NoisyAlloc(i); }));
  291. // Return-by-value:
  292. pyNoisyAlloc.def(py::init([](double d, int) { return NoisyAlloc(d); }));
  293. // Old-style placement new init; requires preallocation
  294. ignoreOldStyleInitWarnings([&pyNoisyAlloc]() {
  295. pyNoisyAlloc.def("__init__", [](NoisyAlloc &a, double d, double) { new (&a) NoisyAlloc(d); });
  296. });
  297. // Requires deallocation of previous overload preallocated value:
  298. pyNoisyAlloc.def(py::init([](int i, double) { return new NoisyAlloc(i); }));
  299. // Regular again: requires yet another preallocation
  300. ignoreOldStyleInitWarnings([&pyNoisyAlloc]() {
  301. pyNoisyAlloc.def("__init__", [](NoisyAlloc &a, int i, std::string) { new (&a) NoisyAlloc(i); });
  302. });
  303. // static_assert testing (the following def's should all fail with appropriate compilation errors):
  304. #if 0
  305. struct BadF1Base {};
  306. struct BadF1 : BadF1Base {};
  307. struct PyBadF1 : BadF1 {};
  308. py::class_<BadF1, PyBadF1, std::shared_ptr<BadF1>> bf1(m, "BadF1");
  309. // wrapped factory function must return a compatible pointer, holder, or value
  310. bf1.def(py::init([]() { return 3; }));
  311. // incompatible factory function pointer return type
  312. bf1.def(py::init([]() { static int three = 3; return &three; }));
  313. // incompatible factory function std::shared_ptr<T> return type: cannot convert shared_ptr<T> to holder
  314. // (non-polymorphic base)
  315. bf1.def(py::init([]() { return std::shared_ptr<BadF1Base>(new BadF1()); }));
  316. #endif
  317. }