pybind11/tests/test_factory_constructors.cpp

360 lines
16 KiB
C++
Raw Normal View History

Allow binding factory functions as constructors This allows you to use: cls.def(py::init(&factory_function)); where `factory_function` returns a pointer, holder, or value of the class type (or a derived type). Various compile-time checks (static_asserts) are performed to ensure the function is valid, and various run-time type checks where necessary. Some other details of this feature: - The `py::init` name doesn't conflict with the templated no-argument `py::init<...>()`, but keeps the naming consistent: the existing templated, no-argument one wraps constructors, the no-template, function-argument one wraps factory functions. - If returning a CppClass (whether by value or pointer) when an CppAlias is required (i.e. python-side inheritance and a declared alias), a dynamic_cast to the alias is attempted (for the pointer version); if it fails, or if returned by value, an Alias(Class &&) constructor is invoked. If this constructor doesn't exist, a runtime error occurs. - for holder returns when an alias is required, we try a dynamic_cast of the wrapped pointer to the alias to see if it is already an alias instance; if it isn't, we raise an error. - `py::init(class_factory, alias_factory)` is also available that takes two factories: the first is called when an alias is not needed, the second when it is. - Reimplement factory instance clearing. The previous implementation failed under python-side multiple inheritance: *each* inherited type's factory init would clear the instance instead of only setting its own type value. The new implementation here clears just the relevant value pointer. - dealloc is updated to explicitly set the leftover value pointer to nullptr and the `holder_constructed` flag to false so that it can be used to clear preallocated value without needing to rebuild the instance internals data. - Added various tests to test out new allocation/deallocation code. - With preallocation now done lazily, init factory holders can completely avoid the extra overhead of needing an extra allocation/deallocation. - Updated documentation to make factory constructors the default advanced constructor style. - If an `__init__` is called a second time, we have two choices: we can throw away the first instance, replacing it with the second; or we can ignore the second call. The latter is slightly easier, so do that.
2017-06-13 01:52:48 +00:00
/*
tests/test_factory_constructors.cpp -- tests construction from a factory function
via py::init_factory()
Copyright (c) 2017 Jason Rhinelander <jason@imaginary.ca>
All rights reserved. Use of this source code is governed by a
BSD-style license that can be found in the LICENSE file.
*/
#include "pybind11_tests.h"
#include "constructor_stats.h"
#include <cmath>
#include <new>
Allow binding factory functions as constructors This allows you to use: cls.def(py::init(&factory_function)); where `factory_function` returns a pointer, holder, or value of the class type (or a derived type). Various compile-time checks (static_asserts) are performed to ensure the function is valid, and various run-time type checks where necessary. Some other details of this feature: - The `py::init` name doesn't conflict with the templated no-argument `py::init<...>()`, but keeps the naming consistent: the existing templated, no-argument one wraps constructors, the no-template, function-argument one wraps factory functions. - If returning a CppClass (whether by value or pointer) when an CppAlias is required (i.e. python-side inheritance and a declared alias), a dynamic_cast to the alias is attempted (for the pointer version); if it fails, or if returned by value, an Alias(Class &&) constructor is invoked. If this constructor doesn't exist, a runtime error occurs. - for holder returns when an alias is required, we try a dynamic_cast of the wrapped pointer to the alias to see if it is already an alias instance; if it isn't, we raise an error. - `py::init(class_factory, alias_factory)` is also available that takes two factories: the first is called when an alias is not needed, the second when it is. - Reimplement factory instance clearing. The previous implementation failed under python-side multiple inheritance: *each* inherited type's factory init would clear the instance instead of only setting its own type value. The new implementation here clears just the relevant value pointer. - dealloc is updated to explicitly set the leftover value pointer to nullptr and the `holder_constructed` flag to false so that it can be used to clear preallocated value without needing to rebuild the instance internals data. - Added various tests to test out new allocation/deallocation code. - With preallocation now done lazily, init factory holders can completely avoid the extra overhead of needing an extra allocation/deallocation. - Updated documentation to make factory constructors the default advanced constructor style. - If an `__init__` is called a second time, we have two choices: we can throw away the first instance, replacing it with the second; or we can ignore the second call. The latter is slightly easier, so do that.
2017-06-13 01:52:48 +00:00
// Classes for testing python construction via C++ factory function:
// Not publicly constructible, copyable, or movable:
Allow binding factory functions as constructors This allows you to use: cls.def(py::init(&factory_function)); where `factory_function` returns a pointer, holder, or value of the class type (or a derived type). Various compile-time checks (static_asserts) are performed to ensure the function is valid, and various run-time type checks where necessary. Some other details of this feature: - The `py::init` name doesn't conflict with the templated no-argument `py::init<...>()`, but keeps the naming consistent: the existing templated, no-argument one wraps constructors, the no-template, function-argument one wraps factory functions. - If returning a CppClass (whether by value or pointer) when an CppAlias is required (i.e. python-side inheritance and a declared alias), a dynamic_cast to the alias is attempted (for the pointer version); if it fails, or if returned by value, an Alias(Class &&) constructor is invoked. If this constructor doesn't exist, a runtime error occurs. - for holder returns when an alias is required, we try a dynamic_cast of the wrapped pointer to the alias to see if it is already an alias instance; if it isn't, we raise an error. - `py::init(class_factory, alias_factory)` is also available that takes two factories: the first is called when an alias is not needed, the second when it is. - Reimplement factory instance clearing. The previous implementation failed under python-side multiple inheritance: *each* inherited type's factory init would clear the instance instead of only setting its own type value. The new implementation here clears just the relevant value pointer. - dealloc is updated to explicitly set the leftover value pointer to nullptr and the `holder_constructed` flag to false so that it can be used to clear preallocated value without needing to rebuild the instance internals data. - Added various tests to test out new allocation/deallocation code. - With preallocation now done lazily, init factory holders can completely avoid the extra overhead of needing an extra allocation/deallocation. - Updated documentation to make factory constructors the default advanced constructor style. - If an `__init__` is called a second time, we have two choices: we can throw away the first instance, replacing it with the second; or we can ignore the second call. The latter is slightly easier, so do that.
2017-06-13 01:52:48 +00:00
class TestFactory1 {
friend class TestFactoryHelper;
TestFactory1() : value("(empty)") { print_default_created(this); }
TestFactory1(int v) : value(std::to_string(v)) { print_created(this, value); }
TestFactory1(std::string v) : value(std::move(v)) { print_created(this, value); }
TestFactory1(TestFactory1 &&) = delete;
TestFactory1(const TestFactory1 &) = delete;
TestFactory1 &operator=(TestFactory1 &&) = delete;
TestFactory1 &operator=(const TestFactory1 &) = delete;
public:
std::string value;
~TestFactory1() { print_destroyed(this); }
};
// Non-public construction, but moveable:
class TestFactory2 {
friend class TestFactoryHelper;
TestFactory2() : value("(empty2)") { print_default_created(this); }
TestFactory2(int v) : value(std::to_string(v)) { print_created(this, value); }
TestFactory2(std::string v) : value(std::move(v)) { print_created(this, value); }
public:
TestFactory2(TestFactory2 &&m) { value = std::move(m.value); print_move_created(this); }
TestFactory2 &operator=(TestFactory2 &&m) { value = std::move(m.value); print_move_assigned(this); return *this; }
std::string value;
~TestFactory2() { print_destroyed(this); }
};
// Mixed direct/factory construction:
class TestFactory3 {
protected:
friend class TestFactoryHelper;
TestFactory3() : value("(empty3)") { print_default_created(this); }
TestFactory3(int v) : value(std::to_string(v)) { print_created(this, value); }
public:
TestFactory3(std::string v) : value(std::move(v)) { print_created(this, value); }
TestFactory3(TestFactory3 &&m) { value = std::move(m.value); print_move_created(this); }
TestFactory3 &operator=(TestFactory3 &&m) { value = std::move(m.value); print_move_assigned(this); return *this; }
std::string value;
virtual ~TestFactory3() { print_destroyed(this); }
};
// Inheritance test
class TestFactory4 : public TestFactory3 {
public:
TestFactory4() : TestFactory3() { print_default_created(this); }
TestFactory4(int v) : TestFactory3(v) { print_created(this, v); }
~TestFactory4() override { print_destroyed(this); }
Allow binding factory functions as constructors This allows you to use: cls.def(py::init(&factory_function)); where `factory_function` returns a pointer, holder, or value of the class type (or a derived type). Various compile-time checks (static_asserts) are performed to ensure the function is valid, and various run-time type checks where necessary. Some other details of this feature: - The `py::init` name doesn't conflict with the templated no-argument `py::init<...>()`, but keeps the naming consistent: the existing templated, no-argument one wraps constructors, the no-template, function-argument one wraps factory functions. - If returning a CppClass (whether by value or pointer) when an CppAlias is required (i.e. python-side inheritance and a declared alias), a dynamic_cast to the alias is attempted (for the pointer version); if it fails, or if returned by value, an Alias(Class &&) constructor is invoked. If this constructor doesn't exist, a runtime error occurs. - for holder returns when an alias is required, we try a dynamic_cast of the wrapped pointer to the alias to see if it is already an alias instance; if it isn't, we raise an error. - `py::init(class_factory, alias_factory)` is also available that takes two factories: the first is called when an alias is not needed, the second when it is. - Reimplement factory instance clearing. The previous implementation failed under python-side multiple inheritance: *each* inherited type's factory init would clear the instance instead of only setting its own type value. The new implementation here clears just the relevant value pointer. - dealloc is updated to explicitly set the leftover value pointer to nullptr and the `holder_constructed` flag to false so that it can be used to clear preallocated value without needing to rebuild the instance internals data. - Added various tests to test out new allocation/deallocation code. - With preallocation now done lazily, init factory holders can completely avoid the extra overhead of needing an extra allocation/deallocation. - Updated documentation to make factory constructors the default advanced constructor style. - If an `__init__` is called a second time, we have two choices: we can throw away the first instance, replacing it with the second; or we can ignore the second call. The latter is slightly easier, so do that.
2017-06-13 01:52:48 +00:00
};
// Another class for an invalid downcast test
class TestFactory5 : public TestFactory3 {
public:
TestFactory5(int i) : TestFactory3(i) { print_created(this, i); }
~TestFactory5() override { print_destroyed(this); }
Allow binding factory functions as constructors This allows you to use: cls.def(py::init(&factory_function)); where `factory_function` returns a pointer, holder, or value of the class type (or a derived type). Various compile-time checks (static_asserts) are performed to ensure the function is valid, and various run-time type checks where necessary. Some other details of this feature: - The `py::init` name doesn't conflict with the templated no-argument `py::init<...>()`, but keeps the naming consistent: the existing templated, no-argument one wraps constructors, the no-template, function-argument one wraps factory functions. - If returning a CppClass (whether by value or pointer) when an CppAlias is required (i.e. python-side inheritance and a declared alias), a dynamic_cast to the alias is attempted (for the pointer version); if it fails, or if returned by value, an Alias(Class &&) constructor is invoked. If this constructor doesn't exist, a runtime error occurs. - for holder returns when an alias is required, we try a dynamic_cast of the wrapped pointer to the alias to see if it is already an alias instance; if it isn't, we raise an error. - `py::init(class_factory, alias_factory)` is also available that takes two factories: the first is called when an alias is not needed, the second when it is. - Reimplement factory instance clearing. The previous implementation failed under python-side multiple inheritance: *each* inherited type's factory init would clear the instance instead of only setting its own type value. The new implementation here clears just the relevant value pointer. - dealloc is updated to explicitly set the leftover value pointer to nullptr and the `holder_constructed` flag to false so that it can be used to clear preallocated value without needing to rebuild the instance internals data. - Added various tests to test out new allocation/deallocation code. - With preallocation now done lazily, init factory holders can completely avoid the extra overhead of needing an extra allocation/deallocation. - Updated documentation to make factory constructors the default advanced constructor style. - If an `__init__` is called a second time, we have two choices: we can throw away the first instance, replacing it with the second; or we can ignore the second call. The latter is slightly easier, so do that.
2017-06-13 01:52:48 +00:00
};
class TestFactory6 {
protected:
int value;
bool alias = false;
public:
TestFactory6(int i) : value{i} { print_created(this, i); }
TestFactory6(TestFactory6 &&f) { print_move_created(this); value = f.value; alias = f.alias; }
TestFactory6(const TestFactory6 &f) { print_copy_created(this); value = f.value; alias = f.alias; }
virtual ~TestFactory6() { print_destroyed(this); }
virtual int get() { return value; }
bool has_alias() { return alias; }
};
class PyTF6 : public TestFactory6 {
public:
// Special constructor that allows the factory to construct a PyTF6 from a TestFactory6 only
// when an alias is needed:
PyTF6(TestFactory6 &&base) : TestFactory6(std::move(base)) { alias = true; print_created(this, "move", value); }
PyTF6(int i) : TestFactory6(i) { alias = true; print_created(this, i); }
PyTF6(PyTF6 &&f) : TestFactory6(std::move(f)) { print_move_created(this); }
PyTF6(const PyTF6 &f) : TestFactory6(f) { print_copy_created(this); }
PyTF6(std::string s) : TestFactory6((int) s.size()) { alias = true; print_created(this, s); }
~PyTF6() override { print_destroyed(this); }
int get() override { PYBIND11_OVERRIDE(int, TestFactory6, get, /*no args*/); }
Allow binding factory functions as constructors This allows you to use: cls.def(py::init(&factory_function)); where `factory_function` returns a pointer, holder, or value of the class type (or a derived type). Various compile-time checks (static_asserts) are performed to ensure the function is valid, and various run-time type checks where necessary. Some other details of this feature: - The `py::init` name doesn't conflict with the templated no-argument `py::init<...>()`, but keeps the naming consistent: the existing templated, no-argument one wraps constructors, the no-template, function-argument one wraps factory functions. - If returning a CppClass (whether by value or pointer) when an CppAlias is required (i.e. python-side inheritance and a declared alias), a dynamic_cast to the alias is attempted (for the pointer version); if it fails, or if returned by value, an Alias(Class &&) constructor is invoked. If this constructor doesn't exist, a runtime error occurs. - for holder returns when an alias is required, we try a dynamic_cast of the wrapped pointer to the alias to see if it is already an alias instance; if it isn't, we raise an error. - `py::init(class_factory, alias_factory)` is also available that takes two factories: the first is called when an alias is not needed, the second when it is. - Reimplement factory instance clearing. The previous implementation failed under python-side multiple inheritance: *each* inherited type's factory init would clear the instance instead of only setting its own type value. The new implementation here clears just the relevant value pointer. - dealloc is updated to explicitly set the leftover value pointer to nullptr and the `holder_constructed` flag to false so that it can be used to clear preallocated value without needing to rebuild the instance internals data. - Added various tests to test out new allocation/deallocation code. - With preallocation now done lazily, init factory holders can completely avoid the extra overhead of needing an extra allocation/deallocation. - Updated documentation to make factory constructors the default advanced constructor style. - If an `__init__` is called a second time, we have two choices: we can throw away the first instance, replacing it with the second; or we can ignore the second call. The latter is slightly easier, so do that.
2017-06-13 01:52:48 +00:00
};
class TestFactory7 {
protected:
int value;
bool alias = false;
public:
TestFactory7(int i) : value{i} { print_created(this, i); }
TestFactory7(TestFactory7 &&f) { print_move_created(this); value = f.value; alias = f.alias; }
TestFactory7(const TestFactory7 &f) { print_copy_created(this); value = f.value; alias = f.alias; }
virtual ~TestFactory7() { print_destroyed(this); }
virtual int get() { return value; }
bool has_alias() { return alias; }
};
class PyTF7 : public TestFactory7 {
public:
PyTF7(int i) : TestFactory7(i) { alias = true; print_created(this, i); }
PyTF7(PyTF7 &&f) : TestFactory7(std::move(f)) { print_move_created(this); }
PyTF7(const PyTF7 &f) : TestFactory7(f) { print_copy_created(this); }
~PyTF7() override { print_destroyed(this); }
int get() override { PYBIND11_OVERRIDE(int, TestFactory7, get, /*no args*/); }
Allow binding factory functions as constructors This allows you to use: cls.def(py::init(&factory_function)); where `factory_function` returns a pointer, holder, or value of the class type (or a derived type). Various compile-time checks (static_asserts) are performed to ensure the function is valid, and various run-time type checks where necessary. Some other details of this feature: - The `py::init` name doesn't conflict with the templated no-argument `py::init<...>()`, but keeps the naming consistent: the existing templated, no-argument one wraps constructors, the no-template, function-argument one wraps factory functions. - If returning a CppClass (whether by value or pointer) when an CppAlias is required (i.e. python-side inheritance and a declared alias), a dynamic_cast to the alias is attempted (for the pointer version); if it fails, or if returned by value, an Alias(Class &&) constructor is invoked. If this constructor doesn't exist, a runtime error occurs. - for holder returns when an alias is required, we try a dynamic_cast of the wrapped pointer to the alias to see if it is already an alias instance; if it isn't, we raise an error. - `py::init(class_factory, alias_factory)` is also available that takes two factories: the first is called when an alias is not needed, the second when it is. - Reimplement factory instance clearing. The previous implementation failed under python-side multiple inheritance: *each* inherited type's factory init would clear the instance instead of only setting its own type value. The new implementation here clears just the relevant value pointer. - dealloc is updated to explicitly set the leftover value pointer to nullptr and the `holder_constructed` flag to false so that it can be used to clear preallocated value without needing to rebuild the instance internals data. - Added various tests to test out new allocation/deallocation code. - With preallocation now done lazily, init factory holders can completely avoid the extra overhead of needing an extra allocation/deallocation. - Updated documentation to make factory constructors the default advanced constructor style. - If an `__init__` is called a second time, we have two choices: we can throw away the first instance, replacing it with the second; or we can ignore the second call. The latter is slightly easier, so do that.
2017-06-13 01:52:48 +00:00
};
class TestFactoryHelper {
public:
// Non-movable, non-copyable type:
// Return via pointer:
static TestFactory1 *construct1() { return new TestFactory1(); }
// Holder:
static std::unique_ptr<TestFactory1> construct1(int a) { return std::unique_ptr<TestFactory1>(new TestFactory1(a)); }
// pointer again
static TestFactory1 *construct1_string(std::string a) { return new TestFactory1(a); }
// Moveable type:
// pointer:
static TestFactory2 *construct2() { return new TestFactory2(); }
// holder:
static std::unique_ptr<TestFactory2> construct2(int a) { return std::unique_ptr<TestFactory2>(new TestFactory2(a)); }
// by value moving:
static TestFactory2 construct2(std::string a) { return TestFactory2(a); }
// shared_ptr holder type:
// pointer:
static TestFactory3 *construct3() { return new TestFactory3(); }
// holder:
static std::shared_ptr<TestFactory3> construct3(int a) { return std::shared_ptr<TestFactory3>(new TestFactory3(a)); }
};
Adding py::smart_holder (for smart-pointer interoperability). (#2672) * Adding test_unique_ptr_member (for desired PyCLIF behavior). See also: https://github.com/pybind/pybind11/issues/2583 Does not build with upstream master or https://github.com/pybind/pybind11/pull/2047, but builds with https://github.com/RobotLocomotion/pybind11 and almost runs: ``` Running tests in directory "/usr/local/google/home/rwgk/forked/EricCousineau-TRI/pybind11/tests": ================================================================================= test session starts ================================================================================= platform linux -- Python 3.8.5, pytest-5.4.3, py-1.9.0, pluggy-0.13.1 rootdir: /usr/local/google/home/rwgk/forked/EricCousineau-TRI/pybind11/tests, inifile: pytest.ini collected 2 items test_unique_ptr_member.py .F [100%] ====================================================================================== FAILURES ======================================================================================= _____________________________________________________________________________ test_pointee_and_ptr_owner ______________________________________________________________________________ def test_pointee_and_ptr_owner(): obj = m.pointee() assert obj.get_int() == 213 m.ptr_owner(obj) with pytest.raises(ValueError) as exc_info: > obj.get_int() E Failed: DID NOT RAISE <class 'ValueError'> test_unique_ptr_member.py:17: Failed ============================================================================= 1 failed, 1 passed in 0.06s ============================================================================= ``` * unique_ptr or shared_ptr return * new test_variant_unique_shared with vptr_holder prototype * moving prototype code to pybind11/vptr_holder.h, adding type_caster specialization to make the bindings involving unique_ptr passing compile, but load and cast implementations are missing * disabling GitHub Actions on pull_request (for this PR) * disabling AppVeyor (for this PR) * TRIGGER_SEGSEV macro, annotations for GET_STACK (vptr::get), GET_INT_STACK (pointee) * adding test_promotion_of_disowned_to_shared * Copying tests as-is from xxx_value_ptr_xxx_holder branch. https://github.com/rwgk/pybind11/tree/xxx_value_ptr_xxx_holder Systematically exercising returning and passing unique_ptr<T>, shared_ptr<T> with unique_ptr, shared_ptr holder. Observations: test_holder_unique_ptr: make_unique_pointee OK pass_unique_pointee BUILD_FAIL (as documented) make_shared_pointee Abort free(): double free detected pass_shared_pointee RuntimeError: Unable to load a custom holder type from a default-holder instance test_holder_shared_ptr: make_unique_pointee Segmentation fault (#1138) pass_unique_pointee BUILD_FAIL (as documented) make_shared_pointee OK pass_shared_pointee OK * Copying tests as-is from xxx_value_ptr_xxx_holder branch. https://github.com/rwgk/pybind11/tree/xxx_value_ptr_xxx_holder Systematically exercising casting between shared_ptr<base>, shared_ptr<derived>. * Demonstration of Undefined Behavior in handling of shared_ptr holder. Based on https://godbolt.org/z/4fdjaW by jorgbrown@ (thanks Jorg!). * Additional demonstration of Undefined Behavior in handling of shared_ptr holder. * fixing up-down mixup in comment * Demonstration of Undefined Behavior in handling of polymorphic pointers. (This demo does NOT involve smart pointers at all, unlike the otherwise similar test_smart_ptr_private_first_base.) * minor test_private_first_base.cpp simplification (after discovering that this can be wrapped with Boost.Python, using boost::noncopyable) * pybind11 equivalent of Boost.Python test similar to reproducer under #1333 * Snapshot of WIP, TODO: shared_ptr deleter with on/off switch * Adding vptr_deleter. * Adding from/as unique_ptr<T> and unique_ptr<T, D>. * Adding from_shared_ptr. Some polishing. * New tests/core/smart_holder_poc_test.cpp, using Catch2. * Adding in vptr_deleter_guard_flag. * Improved labeling of TEST_CASEs. * Shuffling existing TEST_CASEs into systematic matrix. * Implementing all [S]uccess tests. * Implementing all [E]xception tests. * Testing of exceptions not covered by the from-as matrix. * Adding top-level comment. * Converting from methods to factory functions (no functional change). * Removing obsolete and very incomplete test (replaced by Catch2-based test). * Removing stray file. * Adding type_caster_bare_interface_demo. * Adding shared_ptr<mpty>, shared_ptr<mpty const> casters. * Adding unique_ptr<mpty>, unique_ptr<mpty const> casters. * Pure copy of `class class_` implementation in pybind11.h (master commit 98f1bbb8004f654ba9e26717bdf5912fb899b05a). * classh.h: renaming of class_ to classh + namespace; forking test_classh_wip from test_type_caster_bare_interface_demo. * Hard-coding smart_holder into classh. * Adding mpty::mtxt string member. * Adding isinstance<mpty> in type_caster::load functions. * Adding rvalue_ref, renaming const_value_ref to lvalue_ref & removing const. * Retrieving smart_holder pointer in type_caster<mpty>::load, and using it cast_op operators. * Factoring out smart_holder_type_caster_load. * Retrieving smart_holder pointer in type_caster<std::shared_ptr<mpty[ const]>>::load, and using it cast_op operators. * Improved error messaging: Cannot disown nullptr (as_unique_ptr). * Retrieving smart_holder pointer in type_caster<std::unique_ptr<mpty[ const]>>::load, and using it cast_op operators. * Pure `clang-format --style=file -i` change. * Pure `clang-format --style=file -i` change, with two `clang-format off` directives. * Fixing oversight (discovered by flake8). * flake8 cleanup * Systematically setting mtxt for all rtrn_mpty_* functions (preparation, the values are not actually used yet). * static cast handle for rtrn_cptr works by simply dropping in code from type_caster_base (marked with comments). * static cast handle for rtrn_cref works by simply dropping in code from type_caster_base (marked with comments). rtrn_mref and rtrn_mptr work via const_cast (to add const). * static cast handle for rtrn_valu works by simply dropping in code from type_caster_base (marked with comments). rtrn_rref raises a RuntimeError, to be investigated. * Copying type_caster_generic::cast into type_caster<mpty> as-is (preparation for handling smart pointers). * Pure clang-format change (applied to original type_caster_generic::cast). * Adding comment re potential use_count data race. * static handle cast implementations for rtrn_shmp, rtrn_shcp. * Adding MISSING comments in operator std::unique_ptr<mpty[ const]>. * static handle cast implementations for rtrn_uqmp, rtrn_uqcp. * Bug fix: vptr_deleter_armed_flag_ptr has to live on the heap. See new bullet point in comment section near the top. The variable was also renamed to reflect its function more accurately. * Fixing bugs discovered by ASAN. The code is now ASAN, MSAN, UBSAN clean. * Making test_type_caster_bare_interface_demo.cpp slightly more realistic, ASAN, MSAN, UBSAN clean. * Calling deregister_instance after disowning via unique_ptr. * Removing enable_shared_from_this stub, simplifying existing code, clang-format. Open question, with respect to the original code: https://github.com/pybind/pybind11/blob/76a160070b369f8d82b945c97924227e8b835c94/include/pybind11/pybind11.h#L1510 To me it looks like the exact situation marked as `std::shared_ptr<Good> gp1 = not_so_good.getptr();` here: https://en.cppreference.com/w/cpp/memory/enable_shared_from_this The comment there is: `// undefined behavior (until C++17) and std::bad_weak_ptr thrown (since C++17)` Does the existing code have UB pre C++17? I'll leave handling of enable_shared_from_this for later, as the need arises. * Cosmetical change around helper functions. * Using type_caster_base<mpty>::src_and_type directly, removing copy. Also renaming one cast to cast_const_raw_ptr, for clarity. * Fixing clang-format oversight. * Using factored-out make_constructor (PR #2798), removing duplicate code. * Inserting additional assert to ensure a returned unique_ptr is always a new Python instance. * Adding minor comment (change to internals needed to distinguish uninitialized/disowned in error message). * Factoring out find_existing_python_instance(). * Moving factored-out make_constructor to test_classh_wip.cpp, restoring previous version of cast.h. This is currently the most practical approach. See PR #2798 for background. * Copying classh type_casters from test_classh_wip.cpp UNMODIFIED, as a baseline for generalizing the code. * Using pybind11/detail/classh_type_casters.h from test_classh_wip.cpp. * Adding & using PYBIND11_CLASSH_TYPE_CASTERS define. * Adding test_classh_inheritance, currently failing (passes with class_). * Removing .clang-format before git rebase master (where the file was added). * Bringing back .clang-format, the previous rm was a bad idea. * Folding in modified_type_caster_generic_load_impl, just enough to pass test_class_wip. test_classh_inheritance is still failing, but with a different error: [RuntimeError: Incompatible type (as_raw_ptr_unowned).] * Minimal changes needed to pass test_classh_inheritance. * First pass adjusting try_implicit_casts and try_load_foreign_module_local to capture loaded_v_h, but untested and guarded with pybind11_failure("Untested"). This was done mainly to determine general feasibility. Note the TODO in pybind11.h, where type_caster_generic::local_load is currently hard-coded. test_classh_wip and test_classh_inheritance still pass, as before. * Decoupling generic_type from type_caster_generic. * Changes and tests covering classh_type_casters try_implicit_casts. * Minimal test covering classh_type_casters load_impl Case 2b. * Removing stray isinstance<T>(src): it interferes with the py::module_local feature. Adding missing #includes. * Tests for classh py::module_local() feature. * Pure renaming of function names in test_classh_inheritance, similar to the systematic approach used in test_class_wip. NO functional changes. * Pure renaming of function and variable names, for better generalization when convoluting with inheritance. NO functional changes. * Adopting systematic naming scheme from test_classh_wip. NO functional changes. * Moving const after type name, for functions that cover a systematic scheme. NO functional changes. * Adding smart_holder_type_caster_load::loaded_as_shared_ptr, currently bypassing smart_holder shared_ptr tracking completely, but the tests pass and are sanitizer clean. * Removing rtti_held from smart_holder. See updated comment. * Cleaning up loaded_as_raw_ptr_unowned, loaded_as_shared_ptr. * Factoring out convert_type and folding into loaded_as_unique_ptr. * Folding convert_type into lvalue_ref and rvalue_ref paths. Some smart_holder_type_caster_load cleanup. * Using unique_ptr in local_load to replace static variable. Also adding local_load_safety_guard. * Converting test_unique_ptr_member to using classh: fully working, ASAN, MSAN, UBSAN clean. * Removing debugging comments (GET_STACK, GET_INT_STACK). cast.h is identical to current master again, pybind11.h only has the generic_type::initialize(..., &type_caster_generic::local_load) change. * Purging obsolete pybind11/vptr_holder.h and associated test. * Moving several tests to github.com/rwgk/rwgk_tbx/tree/main/pybind11_tests https://github.com/rwgk/rwgk_tbx/commit/a2c2f88174a30f5de80d7d26e0f77c7b60f5fb85 These tests are from experimenting, and for demonstrating UB in pybind11 multiple inheritance handling ("first_base"), to be fixed later. * Adding py::smart_holder support to py::class_, purging py::classh completely. * Renaming files in include directory, creating pybind11/smart_holder.h. * Renaming all "classh" to "smart_holder" in pybind11/detail/smart_holder_type_casters.h. The user-facing macro is now PYBIND11_SMART_HOLDER_TYPE_CASTERS. * Systematically renaming tests to use "class_sh" in the name. * Renaming test_type_caster_bare_interface_demo to test_type_caster_bare_interface. * Renaming new tests/core subdirectory to tests/pure_cpp. * Adding new tests to CMake config, resetting CI config. * Changing CMake file so that test_class_sh_module_local.py actually runs. * clang-tidy fixes. * 32-bit compatibility. * Reusing type_caster_base make_copy_constructor, make_move_constructor with a trick. * CMake COMPARE NATURAL is not available with older versions. * Adding copyright notices to new header files. * Explicitly define copy/move constructors/assignments. * Adding new header files to tests/extra_python_package/test_files.py. * Adding tests/pure_cpp/CMakeLists.txt. * Making use of the new find_existing_python_instance() function factored out with PR #2822. * Moving define PYBIND11_SMART_HOLDER_TYPE_CASTERS(T) down in the file. NO functional changes. Preparation for follow-up work (to keep that diff smaller). * Reintroducing py::classh, this time as a simple alias for py::class_<U, py::smart_holder>. * Replacing detail::is_smart_holder<H> in cast.h with detail::is_smart_holder_type_caster<T>. Moving get_local_load_function_ptr, init_instance_for_type to smart_holder_type_caster_class_hooks. Expanding static_assert in py::type::handle_of<> to accommodate smart_holder_type_casters. * Fixing oversight. * Adding classu alias for class_<U, std::unique_ptr<U>>. * Giving up on idea to use legacy init_instance only if is_base_of<type_caster_generic, type_caster<T>. There are use cases in the wild that define both a custom type_caster and class_. * Removing test_type_caster_bare_interface, which was moved to the separate PR #2834. * Moving up is_smart_holder_type_caster, to also use in cast_is_temporary_value_reference. * Adding smart_holder_type_casters for unique_ptr with custom deleter. SEVERE CODE DUPLICATION. This commit is to establish a baseline for consolidating the unique_ptr code. * Unification of unique_ptr, unique_ptr_with_deleter code in smart_holder_poc.h. Leads to more fitting error messages. Enables use of unique_ptr<T, D> smart_holder_type_casters also for unique_ptr<T>. * Copying files as-is from branch test_unique_ptr_member (PR #2672). * Adding comment, simplifying naming, cmake addition. * Introducing PYBIND11_USE_SMART_HOLDER_AS_DEFAULT macro (tested only undefined; there are many errors with the macro defined). * Removing test_type_caster_bare_interface, which was moved to the separate PR #2834. * Fixing oversight introduced with commit 95425f13d6c14fcb6ee479b62b602dc8a605ec49. * Setting record.default_holder correctly for PYBIND11_USE_SMART_HOLDER_AS_DEFAULT. With this test_class.cpp builds and even mostly runs, except `test_multiple_instances_with_same_pointer`, which segfaults because it is using a `unique_ptr` holder but `smart_holder` `type_caster`. Also adding `static_assert`s to generate build errors for such situations, but guarding with `#if 0` to first pivot to test_factory_constructors.cpp. * Fixing up cast.h and smart_holder.h after rebase. * Removing detail/smart_holder_type_casters.h in separate commit. * Commenting out const in def_buffer(... const). With this, test_buffers builds and runs with PYBIND11_USE_SMART_HOLDER_AS_DEFAULT. Explanation why the const needs to be removed, or fix elsewhere, is still needed, but left for later. * Adding test_class_sh_factory_constructors, reproducing test_factory_constructors failure. Using py::class_ in this commit, to be changed to py::classh for debugging. * Removing include/pybind11/detail/smart_holder_type_casters.h from CMakeLists.txt, test_files.py (since it does not exist in this branch). * Adding // DANGER ZONE reminders. * Converting as many py::class_ to py::classh as possible, not breaking tests. * Adding initimpl::construct() overloads, resulting in test_class_sh_factory_constructors feature parity for py::class_ and py::classh. * Adding enable_if !is_smart_holder_type_caster to existing initimpl::construct(). With this test_factory_constructors.cpp builds with PYBIND11_USE_SMART_HOLDER_AS_DEFAULT. * Disabling shared_ptr&, shared_ptr* tests when building with PYBIND11_USE_SMART_HOLDER_AS_DEFAULT for now, pending work on smart_holder_type_caster<shared_ptr>. * Factoring out struct and class definitions into anonymous namespace. Preparation for building with PYBIND11_USE_SMART_HOLDER_AS_DEFAULT. * Simplifying from_unique_ptr(): typename D = std::default_delete<T> is not needed. Factoring out is_std_default_delete<T>() for consistentcy between ensure_compatible_rtti_uqp_del() and from_unique_ptr(). * Introducing PYBIND11_SMART_POINTER_HOLDER_TYPE_CASTERS. Using it in test_smart_ptr.cpp. With this test_smart_ptr builds with PYBIND11_USE_SMART_HOLDER_AS_DEFAULT and all but one test run successfully. * Introducing 1. type_caster_for_class_, used in PYBIND11_MAKE_OPAQUE, and 2. default_holder_type, used in stl_bind.h. * Using __VA_ARGS__ in PYBIND11_SMART_POINTER_HOLDER_TYPE_CASTERS. * Replacing condense_for_macro with much simpler approach. * Softening static_assert, to only check specifically that smart_holder is not mixed with type_caster_base, and unique_ptr/shared_ptr holders are not mixed with smart_holder_type_casters. * Adding PYBIND11_SMART_POINTER_HOLDER_TYPE_CASTERS in test_class.cpp (with this all but one test succeed with PYBIND11_USE_SMART_HOLDER_AS_DEFAULT). * Adding remaining PYBIND11_SMART_POINTER_HOLDER_TYPE_CASTERS. static_assert for "necessary conditions" for both types of default holder, static_assert for "strict conditions" guarded by new PYBIND11_STRICT_ASSERTS_CLASS_HOLDER_VS_TYPE_CASTER_MIX. All tests build & run as before with unique_ptr as the default holder, all tests build for smart_holder as the default holder, even with the strict static_assert. * Introducing check_is_smart_holder_type_caster() function for runtime check, and reinterpreting record.default_holder as "uses_unique_ptr_holder". With this test_smart_ptr succeeds. (All 42 tests build, 35 tests succeed, 5 run but have some failures, 2 segfault.) * Bug fix: Adding have_value() to smart_holder_type_caster_load. With this test_builtin_casters succeeds. (All 42 tests build, 36 tests succeed, 5 run but have some failures, 1 segfault.) * Adding unowned_void_ptr_from_direct_conversion to modified_type_caster_generic_load_impl. This fixes the last remaining segfault (test_numpy_dtypes). New stats for all tests combined: 12 failed, 458 passed. * Adding "Lazy allocation for unallocated values" (for old-style __init__) into load_value_and_holder. Deferring destruction of disowned holder until clear_instance, to remain inspectable for "uninitialized" or "disowned" detection. New stats for all tests combined: 5 failed, 465 passed. * Changing std::shared_ptr pointer/reference to const pointer/reference. New stats for all tests combined: 4 failed, 466 passed. * Adding return_value_policy::move to permissible policies for unique_ptr returns. New stats for all tests combined: 3 failed, 467 passed. * Overlooked flake8 fixes. * Manipulating failing ConstructorStats test to pass, to be able to run all tests with ASAN. This version of the code is ASAN clean with unique_ptr or smart_holder as the default. This change needs to be reverted after adopting the existing move-only-if-refcount-is-1 logic used by type_caster_base. * Adding copy constructor and move constructor tracking to atyp. Preparation for a follow-up change in smart_holder_type_caster, to make this test sensitive to the changing behavior. [skip ci] * Removing `operator T&&() &&` from smart_holder_type_caster, for compatibility with the behavior of type_caster_base. Enables reverting 2 of 3 test manipulations applied under commit 249df7cbdb09817fed0ddf80f01ba5af12466820. The manipulation in test_factory_constructors.py is NOT reverted in this commit. [skip ci] * Fixing unfortunate editing mishap. This reverts the last remaining test manipulation in commit 249df7cbdb09817fed0ddf80f01ba5af12466820 and makes all existing unit tests pass with smart_holder as default holder. * GitHub CI clang-tidy fixes. * Adding messages to terse `static_assert`s, for pre-C++17 compatibility. * Using @pytest.mark.parametrize to run each assert separately (to see all errors, not just the first). * Systematically removing _atyp from function names, to make the test code simpler. * Using re.match to accommodate variable number of intermediate MvCtor. * Also removing `operator T()` from smart_holder_type_caster, to fix gcc compilation errors. The only loss is pass_rref in test_class_sh_basic. * Systematically replacing `detail::enable_if_t<...smart_holder...>` with `typename std::enable_if<...smart_holder...>::type`. Attempt to work around MSVC 2015 issues, to be tested via GitHub CI. The idea for this change originates from this comment: https://github.com/pybind/pybind11/issues/1616#issuecomment-444536813 * Importing re before pytest after observing a PyPy CI flake when importing pytest first. * Copying MSVC 2015 compatibility change from branch pr2672_use_smart_holder_as_default. * Introducing is_smart_holder_type_caster_base_tag, to keep smart_holder code more disconnected. * Working around MSVC 2015 bug. * Expanding comment for MSVC 2015 workaround. * Systematically changing std::enable_if back to detail::enable_if_t, effectively reverting commit 5d4b6890a337ae1bbaec4091f4195606f89a3b06. * Removing unused smart_holder_type_caster_load::loaded_as_rvalue_ref (it was an oversight that it was not removed with commit 23036a45eb4731a06b488ec1fdf83bca677b7f67). * Removing py::classu, because it does not seem useful enough. * Reverting commit 63495313066119dcf7510c2ae8b468b46c12ef8f by un-commenting `const` in `def_buffer(...)`. To make this possible, `operator T const&` and `operator T const*` in `smart_holder_type_caster` need to be marked as `const` member functions. * Adding construct() overloads for constructing smart_holder from alias unique_ptr, shared_ptr returns. * Adding test_class_sh_factory_constructors.cpp to tests/CMakeLists.txt (fixes oversight, this should have been added long before). * Compatibility with old clang versions (clang 3.6, 3.7 C++11). * Cleaning up changes to existing unit tests. * Systematically adding SMART_HOLDER_WIP tag. Removing minor UNTESTED tags (only the throw are not actually exercised, investing time there has a high cost but very little benefit). * Splitting out smart_holder_type_casters again, into new detail/smart_holder_type_casters_inline_include.h. * Splitting out smart_holder_init_inline_include.h. * Adding additional new include files to CMakeLists.txt, tests/extra_python_package/test_files.py. * clang-format cleanup of most smart_holder code. * Adding source code comments in response to review. * Simple micro-benchmark ("ubench") comparing runtime performance for several holders. Tested using github.com/rwgk/pybind11_scons and Google-internal build system. Sorry, no cmake support at the moment. First results: https://docs.google.com/spreadsheets/d/1InapCYws2Gt-stmFf_Bwl33eOMo3aLE_gc9adveY7RU/edit#gid=0 * Breaking out number_bucket.h, adding hook for also collecting performance data for PyCLIF. * Accounting for ubench in MANIFEST.in (simply prune, for now). * Smarter determination of call_repetitions. [skip ci] * Also scaling performance data to PyCLIF. [skip ci] * Adding ubench/python/number_bucket.clif here for general visibility. * Fix after rebase * Merging detail/smart_holder_init_inline_include.h into detail/init.h. * Renaming detail/is_smart_holder_type_caster.h -> detail/smart_holder_sfinae_hooks_only.h. * Renaming is_smart_holder_type_caster -> type_uses_smart_holder_type_caster for clarity. * Renaming type_caster_type_is_smart_holder_type_caster -> wrapped_type_uses_smart_holder_type_caster for clarity. * Renaming is_smart_holder_type_caster_base_tag -> smart_holder_type_caster_base_tag for simplicity. * Adding copyright notices and minor colateral cleanup. * iwyu cleanup (comprehensive only for cast.h and smart_holder*.h files). * Fixing `git rebase master` accident. * Moving large `pragma warning` block from pybind11.h to detail/common.h. * Fixing another `git rebase master` accident.
2021-02-24 05:50:42 +00:00
PYBIND11_SMART_POINTER_HOLDER_TYPE_CASTERS(TestFactory3, std::shared_ptr<TestFactory3>)
PYBIND11_SMART_POINTER_HOLDER_TYPE_CASTERS(TestFactory4, std::shared_ptr<TestFactory4>)
PYBIND11_SMART_POINTER_HOLDER_TYPE_CASTERS(TestFactory5, std::shared_ptr<TestFactory5>)
PYBIND11_SMART_POINTER_HOLDER_TYPE_CASTERS(TestFactory7, std::shared_ptr<TestFactory7>)
Allow binding factory functions as constructors This allows you to use: cls.def(py::init(&factory_function)); where `factory_function` returns a pointer, holder, or value of the class type (or a derived type). Various compile-time checks (static_asserts) are performed to ensure the function is valid, and various run-time type checks where necessary. Some other details of this feature: - The `py::init` name doesn't conflict with the templated no-argument `py::init<...>()`, but keeps the naming consistent: the existing templated, no-argument one wraps constructors, the no-template, function-argument one wraps factory functions. - If returning a CppClass (whether by value or pointer) when an CppAlias is required (i.e. python-side inheritance and a declared alias), a dynamic_cast to the alias is attempted (for the pointer version); if it fails, or if returned by value, an Alias(Class &&) constructor is invoked. If this constructor doesn't exist, a runtime error occurs. - for holder returns when an alias is required, we try a dynamic_cast of the wrapped pointer to the alias to see if it is already an alias instance; if it isn't, we raise an error. - `py::init(class_factory, alias_factory)` is also available that takes two factories: the first is called when an alias is not needed, the second when it is. - Reimplement factory instance clearing. The previous implementation failed under python-side multiple inheritance: *each* inherited type's factory init would clear the instance instead of only setting its own type value. The new implementation here clears just the relevant value pointer. - dealloc is updated to explicitly set the leftover value pointer to nullptr and the `holder_constructed` flag to false so that it can be used to clear preallocated value without needing to rebuild the instance internals data. - Added various tests to test out new allocation/deallocation code. - With preallocation now done lazily, init factory holders can completely avoid the extra overhead of needing an extra allocation/deallocation. - Updated documentation to make factory constructors the default advanced constructor style. - If an `__init__` is called a second time, we have two choices: we can throw away the first instance, replacing it with the second; or we can ignore the second call. The latter is slightly easier, so do that.
2017-06-13 01:52:48 +00:00
TEST_SUBMODULE(factory_constructors, m) {
// Define various trivial types to allow simpler overload resolution:
py::module_ m_tag = m.def_submodule("tag");
Allow binding factory functions as constructors This allows you to use: cls.def(py::init(&factory_function)); where `factory_function` returns a pointer, holder, or value of the class type (or a derived type). Various compile-time checks (static_asserts) are performed to ensure the function is valid, and various run-time type checks where necessary. Some other details of this feature: - The `py::init` name doesn't conflict with the templated no-argument `py::init<...>()`, but keeps the naming consistent: the existing templated, no-argument one wraps constructors, the no-template, function-argument one wraps factory functions. - If returning a CppClass (whether by value or pointer) when an CppAlias is required (i.e. python-side inheritance and a declared alias), a dynamic_cast to the alias is attempted (for the pointer version); if it fails, or if returned by value, an Alias(Class &&) constructor is invoked. If this constructor doesn't exist, a runtime error occurs. - for holder returns when an alias is required, we try a dynamic_cast of the wrapped pointer to the alias to see if it is already an alias instance; if it isn't, we raise an error. - `py::init(class_factory, alias_factory)` is also available that takes two factories: the first is called when an alias is not needed, the second when it is. - Reimplement factory instance clearing. The previous implementation failed under python-side multiple inheritance: *each* inherited type's factory init would clear the instance instead of only setting its own type value. The new implementation here clears just the relevant value pointer. - dealloc is updated to explicitly set the leftover value pointer to nullptr and the `holder_constructed` flag to false so that it can be used to clear preallocated value without needing to rebuild the instance internals data. - Added various tests to test out new allocation/deallocation code. - With preallocation now done lazily, init factory holders can completely avoid the extra overhead of needing an extra allocation/deallocation. - Updated documentation to make factory constructors the default advanced constructor style. - If an `__init__` is called a second time, we have two choices: we can throw away the first instance, replacing it with the second; or we can ignore the second call. The latter is slightly easier, so do that.
2017-06-13 01:52:48 +00:00
#define MAKE_TAG_TYPE(Name) \
struct Name##_tag {}; \
py::class_<Name##_tag>(m_tag, #Name "_tag").def(py::init<>()); \
m_tag.attr(#Name) = py::cast(Name##_tag{})
MAKE_TAG_TYPE(pointer);
MAKE_TAG_TYPE(unique_ptr);
MAKE_TAG_TYPE(move);
MAKE_TAG_TYPE(shared_ptr);
MAKE_TAG_TYPE(derived);
MAKE_TAG_TYPE(TF4);
MAKE_TAG_TYPE(TF5);
MAKE_TAG_TYPE(null_ptr);
MAKE_TAG_TYPE(null_unique_ptr);
MAKE_TAG_TYPE(null_shared_ptr);
Allow binding factory functions as constructors This allows you to use: cls.def(py::init(&factory_function)); where `factory_function` returns a pointer, holder, or value of the class type (or a derived type). Various compile-time checks (static_asserts) are performed to ensure the function is valid, and various run-time type checks where necessary. Some other details of this feature: - The `py::init` name doesn't conflict with the templated no-argument `py::init<...>()`, but keeps the naming consistent: the existing templated, no-argument one wraps constructors, the no-template, function-argument one wraps factory functions. - If returning a CppClass (whether by value or pointer) when an CppAlias is required (i.e. python-side inheritance and a declared alias), a dynamic_cast to the alias is attempted (for the pointer version); if it fails, or if returned by value, an Alias(Class &&) constructor is invoked. If this constructor doesn't exist, a runtime error occurs. - for holder returns when an alias is required, we try a dynamic_cast of the wrapped pointer to the alias to see if it is already an alias instance; if it isn't, we raise an error. - `py::init(class_factory, alias_factory)` is also available that takes two factories: the first is called when an alias is not needed, the second when it is. - Reimplement factory instance clearing. The previous implementation failed under python-side multiple inheritance: *each* inherited type's factory init would clear the instance instead of only setting its own type value. The new implementation here clears just the relevant value pointer. - dealloc is updated to explicitly set the leftover value pointer to nullptr and the `holder_constructed` flag to false so that it can be used to clear preallocated value without needing to rebuild the instance internals data. - Added various tests to test out new allocation/deallocation code. - With preallocation now done lazily, init factory holders can completely avoid the extra overhead of needing an extra allocation/deallocation. - Updated documentation to make factory constructors the default advanced constructor style. - If an `__init__` is called a second time, we have two choices: we can throw away the first instance, replacing it with the second; or we can ignore the second call. The latter is slightly easier, so do that.
2017-06-13 01:52:48 +00:00
MAKE_TAG_TYPE(base);
MAKE_TAG_TYPE(invalid_base);
MAKE_TAG_TYPE(alias);
MAKE_TAG_TYPE(unaliasable);
MAKE_TAG_TYPE(mixed);
// test_init_factory_basic, test_bad_type
py::class_<TestFactory1>(m, "TestFactory1")
.def(py::init([](unique_ptr_tag, int v) { return TestFactoryHelper::construct1(v); }))
.def(py::init(&TestFactoryHelper::construct1_string)) // raw function pointer
.def(py::init([](pointer_tag) { return TestFactoryHelper::construct1(); }))
.def(py::init([](py::handle, int v, py::handle) { return TestFactoryHelper::construct1(v); }))
.def_readwrite("value", &TestFactory1::value)
;
py::class_<TestFactory2>(m, "TestFactory2")
.def(py::init([](pointer_tag, int v) { return TestFactoryHelper::construct2(v); }))
.def(py::init([](unique_ptr_tag, std::string v) { return TestFactoryHelper::construct2(v); }))
.def(py::init([](move_tag) { return TestFactoryHelper::construct2(); }))
.def_readwrite("value", &TestFactory2::value)
;
// Stateful & reused:
int c = 1;
2017-08-22 14:37:51 +00:00
auto c4a = [c](pointer_tag, TF4_tag, int a) { (void) c; return new TestFactory4(a);};
Allow binding factory functions as constructors This allows you to use: cls.def(py::init(&factory_function)); where `factory_function` returns a pointer, holder, or value of the class type (or a derived type). Various compile-time checks (static_asserts) are performed to ensure the function is valid, and various run-time type checks where necessary. Some other details of this feature: - The `py::init` name doesn't conflict with the templated no-argument `py::init<...>()`, but keeps the naming consistent: the existing templated, no-argument one wraps constructors, the no-template, function-argument one wraps factory functions. - If returning a CppClass (whether by value or pointer) when an CppAlias is required (i.e. python-side inheritance and a declared alias), a dynamic_cast to the alias is attempted (for the pointer version); if it fails, or if returned by value, an Alias(Class &&) constructor is invoked. If this constructor doesn't exist, a runtime error occurs. - for holder returns when an alias is required, we try a dynamic_cast of the wrapped pointer to the alias to see if it is already an alias instance; if it isn't, we raise an error. - `py::init(class_factory, alias_factory)` is also available that takes two factories: the first is called when an alias is not needed, the second when it is. - Reimplement factory instance clearing. The previous implementation failed under python-side multiple inheritance: *each* inherited type's factory init would clear the instance instead of only setting its own type value. The new implementation here clears just the relevant value pointer. - dealloc is updated to explicitly set the leftover value pointer to nullptr and the `holder_constructed` flag to false so that it can be used to clear preallocated value without needing to rebuild the instance internals data. - Added various tests to test out new allocation/deallocation code. - With preallocation now done lazily, init factory holders can completely avoid the extra overhead of needing an extra allocation/deallocation. - Updated documentation to make factory constructors the default advanced constructor style. - If an `__init__` is called a second time, we have two choices: we can throw away the first instance, replacing it with the second; or we can ignore the second call. The latter is slightly easier, so do that.
2017-06-13 01:52:48 +00:00
// test_init_factory_basic, test_init_factory_casting
py::class_<TestFactory3, std::shared_ptr<TestFactory3>> pyTestFactory3(m, "TestFactory3");
pyTestFactory3
Allow binding factory functions as constructors This allows you to use: cls.def(py::init(&factory_function)); where `factory_function` returns a pointer, holder, or value of the class type (or a derived type). Various compile-time checks (static_asserts) are performed to ensure the function is valid, and various run-time type checks where necessary. Some other details of this feature: - The `py::init` name doesn't conflict with the templated no-argument `py::init<...>()`, but keeps the naming consistent: the existing templated, no-argument one wraps constructors, the no-template, function-argument one wraps factory functions. - If returning a CppClass (whether by value or pointer) when an CppAlias is required (i.e. python-side inheritance and a declared alias), a dynamic_cast to the alias is attempted (for the pointer version); if it fails, or if returned by value, an Alias(Class &&) constructor is invoked. If this constructor doesn't exist, a runtime error occurs. - for holder returns when an alias is required, we try a dynamic_cast of the wrapped pointer to the alias to see if it is already an alias instance; if it isn't, we raise an error. - `py::init(class_factory, alias_factory)` is also available that takes two factories: the first is called when an alias is not needed, the second when it is. - Reimplement factory instance clearing. The previous implementation failed under python-side multiple inheritance: *each* inherited type's factory init would clear the instance instead of only setting its own type value. The new implementation here clears just the relevant value pointer. - dealloc is updated to explicitly set the leftover value pointer to nullptr and the `holder_constructed` flag to false so that it can be used to clear preallocated value without needing to rebuild the instance internals data. - Added various tests to test out new allocation/deallocation code. - With preallocation now done lazily, init factory holders can completely avoid the extra overhead of needing an extra allocation/deallocation. - Updated documentation to make factory constructors the default advanced constructor style. - If an `__init__` is called a second time, we have two choices: we can throw away the first instance, replacing it with the second; or we can ignore the second call. The latter is slightly easier, so do that.
2017-06-13 01:52:48 +00:00
.def(py::init([](pointer_tag, int v) { return TestFactoryHelper::construct3(v); }))
.def(py::init([](shared_ptr_tag) { return TestFactoryHelper::construct3(); }));
ignoreOldStyleInitWarnings([&pyTestFactory3]() {
pyTestFactory3.def("__init__", [](TestFactory3 &self, std::string v) { new (&self) TestFactory3(v); }); // placement-new ctor
});
pyTestFactory3
Allow binding factory functions as constructors This allows you to use: cls.def(py::init(&factory_function)); where `factory_function` returns a pointer, holder, or value of the class type (or a derived type). Various compile-time checks (static_asserts) are performed to ensure the function is valid, and various run-time type checks where necessary. Some other details of this feature: - The `py::init` name doesn't conflict with the templated no-argument `py::init<...>()`, but keeps the naming consistent: the existing templated, no-argument one wraps constructors, the no-template, function-argument one wraps factory functions. - If returning a CppClass (whether by value or pointer) when an CppAlias is required (i.e. python-side inheritance and a declared alias), a dynamic_cast to the alias is attempted (for the pointer version); if it fails, or if returned by value, an Alias(Class &&) constructor is invoked. If this constructor doesn't exist, a runtime error occurs. - for holder returns when an alias is required, we try a dynamic_cast of the wrapped pointer to the alias to see if it is already an alias instance; if it isn't, we raise an error. - `py::init(class_factory, alias_factory)` is also available that takes two factories: the first is called when an alias is not needed, the second when it is. - Reimplement factory instance clearing. The previous implementation failed under python-side multiple inheritance: *each* inherited type's factory init would clear the instance instead of only setting its own type value. The new implementation here clears just the relevant value pointer. - dealloc is updated to explicitly set the leftover value pointer to nullptr and the `holder_constructed` flag to false so that it can be used to clear preallocated value without needing to rebuild the instance internals data. - Added various tests to test out new allocation/deallocation code. - With preallocation now done lazily, init factory holders can completely avoid the extra overhead of needing an extra allocation/deallocation. - Updated documentation to make factory constructors the default advanced constructor style. - If an `__init__` is called a second time, we have two choices: we can throw away the first instance, replacing it with the second; or we can ignore the second call. The latter is slightly easier, so do that.
2017-06-13 01:52:48 +00:00
// factories returning a derived type:
.def(py::init(c4a)) // derived ptr
.def(py::init([](pointer_tag, TF5_tag, int a) { return new TestFactory5(a); }))
// derived shared ptr:
.def(py::init([](shared_ptr_tag, TF4_tag, int a) { return std::make_shared<TestFactory4>(a); }))
.def(py::init([](shared_ptr_tag, TF5_tag, int a) { return std::make_shared<TestFactory5>(a); }))
// Returns nullptr:
.def(py::init([](null_ptr_tag) { return (TestFactory3 *) nullptr; }))
.def(py::init([](null_unique_ptr_tag) { return std::unique_ptr<TestFactory3>(); }))
.def(py::init([](null_shared_ptr_tag) { return std::shared_ptr<TestFactory3>(); }))
Allow binding factory functions as constructors This allows you to use: cls.def(py::init(&factory_function)); where `factory_function` returns a pointer, holder, or value of the class type (or a derived type). Various compile-time checks (static_asserts) are performed to ensure the function is valid, and various run-time type checks where necessary. Some other details of this feature: - The `py::init` name doesn't conflict with the templated no-argument `py::init<...>()`, but keeps the naming consistent: the existing templated, no-argument one wraps constructors, the no-template, function-argument one wraps factory functions. - If returning a CppClass (whether by value or pointer) when an CppAlias is required (i.e. python-side inheritance and a declared alias), a dynamic_cast to the alias is attempted (for the pointer version); if it fails, or if returned by value, an Alias(Class &&) constructor is invoked. If this constructor doesn't exist, a runtime error occurs. - for holder returns when an alias is required, we try a dynamic_cast of the wrapped pointer to the alias to see if it is already an alias instance; if it isn't, we raise an error. - `py::init(class_factory, alias_factory)` is also available that takes two factories: the first is called when an alias is not needed, the second when it is. - Reimplement factory instance clearing. The previous implementation failed under python-side multiple inheritance: *each* inherited type's factory init would clear the instance instead of only setting its own type value. The new implementation here clears just the relevant value pointer. - dealloc is updated to explicitly set the leftover value pointer to nullptr and the `holder_constructed` flag to false so that it can be used to clear preallocated value without needing to rebuild the instance internals data. - Added various tests to test out new allocation/deallocation code. - With preallocation now done lazily, init factory holders can completely avoid the extra overhead of needing an extra allocation/deallocation. - Updated documentation to make factory constructors the default advanced constructor style. - If an `__init__` is called a second time, we have two choices: we can throw away the first instance, replacing it with the second; or we can ignore the second call. The latter is slightly easier, so do that.
2017-06-13 01:52:48 +00:00
.def_readwrite("value", &TestFactory3::value)
;
// test_init_factory_casting
py::class_<TestFactory4, TestFactory3, std::shared_ptr<TestFactory4>>(m, "TestFactory4")
.def(py::init(c4a)) // pointer
;
// Doesn't need to be registered, but registering makes getting ConstructorStats easier:
py::class_<TestFactory5, TestFactory3, std::shared_ptr<TestFactory5>>(m, "TestFactory5");
// test_init_factory_alias
// Alias testing
py::class_<TestFactory6, PyTF6>(m, "TestFactory6")
.def(py::init([](base_tag, int i) { return TestFactory6(i); }))
.def(py::init([](alias_tag, int i) { return PyTF6(i); }))
.def(py::init([](alias_tag, std::string s) { return PyTF6(s); }))
.def(py::init([](alias_tag, pointer_tag, int i) { return new PyTF6(i); }))
.def(py::init([](base_tag, pointer_tag, int i) { return new TestFactory6(i); }))
.def(py::init([](base_tag, alias_tag, pointer_tag, int i) { return (TestFactory6 *) new PyTF6(i); }))
.def("get", &TestFactory6::get)
.def("has_alias", &TestFactory6::has_alias)
.def_static("get_cstats", &ConstructorStats::get<TestFactory6>, py::return_value_policy::reference)
.def_static("get_alias_cstats", &ConstructorStats::get<PyTF6>, py::return_value_policy::reference)
;
// test_init_factory_dual
// Separate alias constructor testing
py::class_<TestFactory7, PyTF7, std::shared_ptr<TestFactory7>>(m, "TestFactory7")
.def(py::init(
[](int i) { return TestFactory7(i); },
[](int i) { return PyTF7(i); }))
.def(py::init(
[](pointer_tag, int i) { return new TestFactory7(i); },
[](pointer_tag, int i) { return new PyTF7(i); }))
.def(py::init(
[](mixed_tag, int i) { return new TestFactory7(i); },
[](mixed_tag, int i) { return PyTF7(i); }))
.def(py::init(
[](mixed_tag, std::string s) { return TestFactory7((int) s.size()); },
[](mixed_tag, std::string s) { return new PyTF7((int) s.size()); }))
.def(py::init(
[](base_tag, pointer_tag, int i) { return new TestFactory7(i); },
[](base_tag, pointer_tag, int i) { return (TestFactory7 *) new PyTF7(i); }))
.def(py::init(
[](alias_tag, pointer_tag, int i) { return new PyTF7(i); },
[](alias_tag, pointer_tag, int i) { return new PyTF7(10*i); }))
.def(py::init(
[](shared_ptr_tag, base_tag, int i) { return std::make_shared<TestFactory7>(i); },
[](shared_ptr_tag, base_tag, int i) { auto *p = new PyTF7(i); return std::shared_ptr<TestFactory7>(p); }))
.def(py::init(
[](shared_ptr_tag, invalid_base_tag, int i) { return std::make_shared<TestFactory7>(i); },
[](shared_ptr_tag, invalid_base_tag, int i) { return std::make_shared<TestFactory7>(i); })) // <-- invalid alias factory
.def("get", &TestFactory7::get)
.def("has_alias", &TestFactory7::has_alias)
.def_static("get_cstats", &ConstructorStats::get<TestFactory7>, py::return_value_policy::reference)
.def_static("get_alias_cstats", &ConstructorStats::get<PyTF7>, py::return_value_policy::reference)
;
// test_placement_new_alternative
// Class with a custom new operator but *without* a placement new operator (issue #948)
class NoPlacementNew {
public:
NoPlacementNew(int i) : i(i) { }
static void *operator new(std::size_t s) {
auto *p = ::operator new(s);
py::print("operator new called, returning", reinterpret_cast<uintptr_t>(p));
return p;
}
static void operator delete(void *p) {
py::print("operator delete called on", reinterpret_cast<uintptr_t>(p));
::operator delete(p);
}
int i;
};
// As of 2.2, `py::init<args>` no longer requires placement new
Allow binding factory functions as constructors This allows you to use: cls.def(py::init(&factory_function)); where `factory_function` returns a pointer, holder, or value of the class type (or a derived type). Various compile-time checks (static_asserts) are performed to ensure the function is valid, and various run-time type checks where necessary. Some other details of this feature: - The `py::init` name doesn't conflict with the templated no-argument `py::init<...>()`, but keeps the naming consistent: the existing templated, no-argument one wraps constructors, the no-template, function-argument one wraps factory functions. - If returning a CppClass (whether by value or pointer) when an CppAlias is required (i.e. python-side inheritance and a declared alias), a dynamic_cast to the alias is attempted (for the pointer version); if it fails, or if returned by value, an Alias(Class &&) constructor is invoked. If this constructor doesn't exist, a runtime error occurs. - for holder returns when an alias is required, we try a dynamic_cast of the wrapped pointer to the alias to see if it is already an alias instance; if it isn't, we raise an error. - `py::init(class_factory, alias_factory)` is also available that takes two factories: the first is called when an alias is not needed, the second when it is. - Reimplement factory instance clearing. The previous implementation failed under python-side multiple inheritance: *each* inherited type's factory init would clear the instance instead of only setting its own type value. The new implementation here clears just the relevant value pointer. - dealloc is updated to explicitly set the leftover value pointer to nullptr and the `holder_constructed` flag to false so that it can be used to clear preallocated value without needing to rebuild the instance internals data. - Added various tests to test out new allocation/deallocation code. - With preallocation now done lazily, init factory holders can completely avoid the extra overhead of needing an extra allocation/deallocation. - Updated documentation to make factory constructors the default advanced constructor style. - If an `__init__` is called a second time, we have two choices: we can throw away the first instance, replacing it with the second; or we can ignore the second call. The latter is slightly easier, so do that.
2017-06-13 01:52:48 +00:00
py::class_<NoPlacementNew>(m, "NoPlacementNew")
.def(py::init<int>())
Allow binding factory functions as constructors This allows you to use: cls.def(py::init(&factory_function)); where `factory_function` returns a pointer, holder, or value of the class type (or a derived type). Various compile-time checks (static_asserts) are performed to ensure the function is valid, and various run-time type checks where necessary. Some other details of this feature: - The `py::init` name doesn't conflict with the templated no-argument `py::init<...>()`, but keeps the naming consistent: the existing templated, no-argument one wraps constructors, the no-template, function-argument one wraps factory functions. - If returning a CppClass (whether by value or pointer) when an CppAlias is required (i.e. python-side inheritance and a declared alias), a dynamic_cast to the alias is attempted (for the pointer version); if it fails, or if returned by value, an Alias(Class &&) constructor is invoked. If this constructor doesn't exist, a runtime error occurs. - for holder returns when an alias is required, we try a dynamic_cast of the wrapped pointer to the alias to see if it is already an alias instance; if it isn't, we raise an error. - `py::init(class_factory, alias_factory)` is also available that takes two factories: the first is called when an alias is not needed, the second when it is. - Reimplement factory instance clearing. The previous implementation failed under python-side multiple inheritance: *each* inherited type's factory init would clear the instance instead of only setting its own type value. The new implementation here clears just the relevant value pointer. - dealloc is updated to explicitly set the leftover value pointer to nullptr and the `holder_constructed` flag to false so that it can be used to clear preallocated value without needing to rebuild the instance internals data. - Added various tests to test out new allocation/deallocation code. - With preallocation now done lazily, init factory holders can completely avoid the extra overhead of needing an extra allocation/deallocation. - Updated documentation to make factory constructors the default advanced constructor style. - If an `__init__` is called a second time, we have two choices: we can throw away the first instance, replacing it with the second; or we can ignore the second call. The latter is slightly easier, so do that.
2017-06-13 01:52:48 +00:00
.def(py::init([]() { return new NoPlacementNew(100); }))
.def_readwrite("i", &NoPlacementNew::i)
;
// test_reallocations
// Class that has verbose operator_new/operator_delete calls
struct NoisyAlloc {
NoisyAlloc(const NoisyAlloc &) = default;
Allow binding factory functions as constructors This allows you to use: cls.def(py::init(&factory_function)); where `factory_function` returns a pointer, holder, or value of the class type (or a derived type). Various compile-time checks (static_asserts) are performed to ensure the function is valid, and various run-time type checks where necessary. Some other details of this feature: - The `py::init` name doesn't conflict with the templated no-argument `py::init<...>()`, but keeps the naming consistent: the existing templated, no-argument one wraps constructors, the no-template, function-argument one wraps factory functions. - If returning a CppClass (whether by value or pointer) when an CppAlias is required (i.e. python-side inheritance and a declared alias), a dynamic_cast to the alias is attempted (for the pointer version); if it fails, or if returned by value, an Alias(Class &&) constructor is invoked. If this constructor doesn't exist, a runtime error occurs. - for holder returns when an alias is required, we try a dynamic_cast of the wrapped pointer to the alias to see if it is already an alias instance; if it isn't, we raise an error. - `py::init(class_factory, alias_factory)` is also available that takes two factories: the first is called when an alias is not needed, the second when it is. - Reimplement factory instance clearing. The previous implementation failed under python-side multiple inheritance: *each* inherited type's factory init would clear the instance instead of only setting its own type value. The new implementation here clears just the relevant value pointer. - dealloc is updated to explicitly set the leftover value pointer to nullptr and the `holder_constructed` flag to false so that it can be used to clear preallocated value without needing to rebuild the instance internals data. - Added various tests to test out new allocation/deallocation code. - With preallocation now done lazily, init factory holders can completely avoid the extra overhead of needing an extra allocation/deallocation. - Updated documentation to make factory constructors the default advanced constructor style. - If an `__init__` is called a second time, we have two choices: we can throw away the first instance, replacing it with the second; or we can ignore the second call. The latter is slightly easier, so do that.
2017-06-13 01:52:48 +00:00
NoisyAlloc(int i) { py::print(py::str("NoisyAlloc(int {})").format(i)); }
NoisyAlloc(double d) { py::print(py::str("NoisyAlloc(double {})").format(d)); }
~NoisyAlloc() { py::print("~NoisyAlloc()"); }
static void *operator new(size_t s) { py::print("noisy new"); return ::operator new(s); }
static void *operator new(size_t, void *p) { py::print("noisy placement new"); return p; }
static void operator delete(void *p, size_t) { py::print("noisy delete"); ::operator delete(p); }
static void operator delete(void *, void *) { py::print("noisy placement delete"); }
#if defined(_MSC_VER) && _MSC_VER < 1910
// MSVC 2015 bug: the above "noisy delete" isn't invoked (fixed in MSVC 2017)
static void operator delete(void *p) { py::print("noisy delete"); ::operator delete(p); }
#endif
};
py::class_<NoisyAlloc> pyNoisyAlloc(m, "NoisyAlloc");
Allow binding factory functions as constructors This allows you to use: cls.def(py::init(&factory_function)); where `factory_function` returns a pointer, holder, or value of the class type (or a derived type). Various compile-time checks (static_asserts) are performed to ensure the function is valid, and various run-time type checks where necessary. Some other details of this feature: - The `py::init` name doesn't conflict with the templated no-argument `py::init<...>()`, but keeps the naming consistent: the existing templated, no-argument one wraps constructors, the no-template, function-argument one wraps factory functions. - If returning a CppClass (whether by value or pointer) when an CppAlias is required (i.e. python-side inheritance and a declared alias), a dynamic_cast to the alias is attempted (for the pointer version); if it fails, or if returned by value, an Alias(Class &&) constructor is invoked. If this constructor doesn't exist, a runtime error occurs. - for holder returns when an alias is required, we try a dynamic_cast of the wrapped pointer to the alias to see if it is already an alias instance; if it isn't, we raise an error. - `py::init(class_factory, alias_factory)` is also available that takes two factories: the first is called when an alias is not needed, the second when it is. - Reimplement factory instance clearing. The previous implementation failed under python-side multiple inheritance: *each* inherited type's factory init would clear the instance instead of only setting its own type value. The new implementation here clears just the relevant value pointer. - dealloc is updated to explicitly set the leftover value pointer to nullptr and the `holder_constructed` flag to false so that it can be used to clear preallocated value without needing to rebuild the instance internals data. - Added various tests to test out new allocation/deallocation code. - With preallocation now done lazily, init factory holders can completely avoid the extra overhead of needing an extra allocation/deallocation. - Updated documentation to make factory constructors the default advanced constructor style. - If an `__init__` is called a second time, we have two choices: we can throw away the first instance, replacing it with the second; or we can ignore the second call. The latter is slightly easier, so do that.
2017-06-13 01:52:48 +00:00
// Since these overloads have the same number of arguments, the dispatcher will try each of
// them until the arguments convert. Thus we can get a pre-allocation here when passing a
// single non-integer:
ignoreOldStyleInitWarnings([&pyNoisyAlloc]() {
pyNoisyAlloc.def("__init__", [](NoisyAlloc *a, int i) { new (a) NoisyAlloc(i); }); // Regular constructor, runs first, requires preallocation
});
pyNoisyAlloc.def(py::init([](double d) { return new NoisyAlloc(d); }));
// The two-argument version: first the factory pointer overload.
pyNoisyAlloc.def(py::init([](int i, int) { return new NoisyAlloc(i); }));
// Return-by-value:
pyNoisyAlloc.def(py::init([](double d, int) { return NoisyAlloc(d); }));
// Old-style placement new init; requires preallocation
ignoreOldStyleInitWarnings([&pyNoisyAlloc]() {
pyNoisyAlloc.def("__init__", [](NoisyAlloc &a, double d, double) { new (&a) NoisyAlloc(d); });
});
// Requires deallocation of previous overload preallocated value:
pyNoisyAlloc.def(py::init([](int i, double) { return new NoisyAlloc(i); }));
// Regular again: requires yet another preallocation
ignoreOldStyleInitWarnings([&pyNoisyAlloc]() {
pyNoisyAlloc.def("__init__", [](NoisyAlloc &a, int i, std::string) { new (&a) NoisyAlloc(i); });
});
Allow binding factory functions as constructors This allows you to use: cls.def(py::init(&factory_function)); where `factory_function` returns a pointer, holder, or value of the class type (or a derived type). Various compile-time checks (static_asserts) are performed to ensure the function is valid, and various run-time type checks where necessary. Some other details of this feature: - The `py::init` name doesn't conflict with the templated no-argument `py::init<...>()`, but keeps the naming consistent: the existing templated, no-argument one wraps constructors, the no-template, function-argument one wraps factory functions. - If returning a CppClass (whether by value or pointer) when an CppAlias is required (i.e. python-side inheritance and a declared alias), a dynamic_cast to the alias is attempted (for the pointer version); if it fails, or if returned by value, an Alias(Class &&) constructor is invoked. If this constructor doesn't exist, a runtime error occurs. - for holder returns when an alias is required, we try a dynamic_cast of the wrapped pointer to the alias to see if it is already an alias instance; if it isn't, we raise an error. - `py::init(class_factory, alias_factory)` is also available that takes two factories: the first is called when an alias is not needed, the second when it is. - Reimplement factory instance clearing. The previous implementation failed under python-side multiple inheritance: *each* inherited type's factory init would clear the instance instead of only setting its own type value. The new implementation here clears just the relevant value pointer. - dealloc is updated to explicitly set the leftover value pointer to nullptr and the `holder_constructed` flag to false so that it can be used to clear preallocated value without needing to rebuild the instance internals data. - Added various tests to test out new allocation/deallocation code. - With preallocation now done lazily, init factory holders can completely avoid the extra overhead of needing an extra allocation/deallocation. - Updated documentation to make factory constructors the default advanced constructor style. - If an `__init__` is called a second time, we have two choices: we can throw away the first instance, replacing it with the second; or we can ignore the second call. The latter is slightly easier, so do that.
2017-06-13 01:52:48 +00:00
// static_assert testing (the following def's should all fail with appropriate compilation errors):
#if 0
struct BadF1Base {};
struct BadF1 : BadF1Base {};
struct PyBadF1 : BadF1 {};
py::class_<BadF1, PyBadF1, std::shared_ptr<BadF1>> bf1(m, "BadF1");
// wrapped factory function must return a compatible pointer, holder, or value
bf1.def(py::init([]() { return 3; }));
// incompatible factory function pointer return type
bf1.def(py::init([]() { static int three = 3; return &three; }));
// incompatible factory function std::shared_ptr<T> return type: cannot convert shared_ptr<T> to holder
// (non-polymorphic base)
bf1.def(py::init([]() { return std::shared_ptr<BadF1Base>(new BadF1()); }));
#endif
}