• Jason Rhinelander's avatar
    Allow binding factory functions as constructors · 464d9896
    Jason Rhinelander authored
    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.
    464d9896
test_factory_constructors.cpp 15.5 KB