Allow passing base types as a template parameter
This allows a slightly cleaner base type specification of:
py::class_<Type, Base>("Type")
as an alternative to
py::class_<Type>("Type", py::base<Base>())
As with the other template parameters, the order relative to the holder
or trampoline types doesn't matter.
This also includes a compile-time assertion failure if attempting to
specify more than one base class (but is easily extendible to support
multiple inheritance, someday, by updating the class_selector::set_bases
function to set multiple bases).
diff --git a/docs/advanced.rst b/docs/advanced.rst
index 6a4a020..748f91e 100644
--- a/docs/advanced.rst
+++ b/docs/advanced.rst
@@ -1227,7 +1227,7 @@
the other existing exception translators.
The ``py::exception`` wrapper for creating custom exceptions cannot (yet)
- be used as a ``py::base``.
+ be used as a base type.
.. _eigen:
@@ -1811,16 +1811,17 @@
.def(py::init<const std::string &>())
.def("bark", &Dog::bark);
-Alternatively, we can rely on the ``base`` tag, which performs an automated
-lookup of the corresponding Python type. However, this also requires invoking
-the ``import`` function once to ensure that the pybind11 binding code of the
-module ``basic`` has been executed.
+Alternatively, you can specify the base class as a template parameter option to
+``class_``, which performs an automated lookup of the corresponding Python
+type. Like the above code, however, this also requires invoking the ``import``
+function once to ensure that the pybind11 binding code of the module ``basic``
+has been executed:
.. code-block:: cpp
py::module::import("basic");
- py::class_<Dog>(m, "Dog", py::base<Pet>())
+ py::class_<Dog, Pet>(m, "Dog")
.def(py::init<const std::string &>())
.def("bark", &Dog::bark);
diff --git a/docs/classes.rst b/docs/classes.rst
index 5afb21e..80f378f 100644
--- a/docs/classes.rst
+++ b/docs/classes.rst
@@ -185,9 +185,10 @@
std::string bark() const { return "woof!"; }
};
-There are two different ways of indicating a hierarchical relationship to
-pybind11: the first is by specifying the C++ base class explicitly during
-construction using the ``base`` attribute:
+There are three different ways of indicating a hierarchical relationship to
+pybind11: the first specifies the C++ base class as an extra template
+parameter of the :class:`class_`; the second uses a special ``base`` attribute
+passed into the constructor:
.. code-block:: cpp
@@ -195,6 +196,12 @@
.def(py::init<const std::string &>())
.def_readwrite("name", &Pet::name);
+ // Method 1: template parameter:
+ py::class_<Dog, Pet /* <- specify C++ parent type */>(m, "Dog")
+ .def(py::init<const std::string &>())
+ .def("bark", &Dog::bark);
+
+ // Method 2: py::base attribute:
py::class_<Dog>(m, "Dog", py::base<Pet>() /* <- specify C++ parent type */)
.def(py::init<const std::string &>())
.def("bark", &Dog::bark);
@@ -208,11 +215,12 @@
pet.def(py::init<const std::string &>())
.def_readwrite("name", &Pet::name);
+ // Method 3: pass parent class_ object:
py::class_<Dog>(m, "Dog", pet /* <- specify Python parent type */)
.def(py::init<const std::string &>())
.def("bark", &Dog::bark);
-Functionality-wise, both approaches are completely equivalent. Afterwards,
+Functionality-wise, all three approaches are completely equivalent. Afterwards,
instances will expose fields and methods of both types:
.. code-block:: pycon