Skip to content

Document how to bind templates #3665

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions docs/advanced/classes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1161,6 +1161,58 @@ error:

.. versionadded:: 2.6

Binding classes with template parameters
========================================

pybind11 can also wrap classes that have template parameters. Consider these classes:

.. code-block:: cpp

struct Cat {};
struct Dog {};

template <typename PetType>
struct Cage {
Cage(PetType& pet);
PetType& get();
};

C++ templates may only be instantiated at compile time, so pybind11 can only
wrap instantiated templated classes. You cannot wrap a non-instantiated template:

.. code-block:: cpp

// BROKEN (this will not compile)
py::class_<Cage>(m, "Cage");
.def("get", &Cage::get);

You must explicitly specify each template/type combination that you want to
wrap separately.

.. code-block:: cpp

// ok
py::class_<Cage<Cat>>(m, "CatCage")
.def("get", &Cage<Cat>::get);

// ok
py::class_<Cage<Dog>>(m, "DogCage")
.def("get", &Cage<Dog>::get);

If your class methods have template parameters you can wrap those as well,
but once again each instantiation must be explicitly specified:

.. code-block:: cpp

typename <typename T>
struct MyClass {
template <typename V>
T fn(V v);
};

py::class<MyClass<int>>(m, "MyClassT")
.def("fn", &MyClass<int>::fn<std::string>);

Custom automatic downcasters
============================

Expand Down
35 changes: 35 additions & 0 deletions docs/advanced/functions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -578,3 +578,38 @@ prefers earlier-defined overloads to later-defined ones.
.. versionadded:: 2.6

The ``py::prepend()`` tag.

Binding functions with template parameters
==========================================

You can bind functions that have template parameters. Here's a function:

.. code-block:: cpp

template <typename T>
void set(T t);

C++ templates cannot be instantiated at runtime, so you cannot bind the
non-instantiated function:

.. code-block:: cpp

// BROKEN (this will not compile)
m.def("set", &set);

You must bind each instantiated function template separately. You may bind
each instantiation with the same name, which will be treated the same as
an overloaded function:

.. code-block:: cpp

m.def("set", &set<int>);
m.def("set", &set<std::string>);

Sometimes it's more clear to bind them with separate names, which is also
an option:

.. code-block:: cpp

m.def("setInt", &set<int>);
m.def("setString", &set<std::string>);