Skip to content

Commit af6c352

Browse files
committed
Document how to bind templates
1 parent ec81e8e commit af6c352

File tree

2 files changed

+86
-0
lines changed

2 files changed

+86
-0
lines changed

docs/advanced/classes.rst

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1161,6 +1161,58 @@ error:
11611161

11621162
.. versionadded:: 2.6
11631163

1164+
Binding classes with template parameters
1165+
========================================
1166+
1167+
pybind11 can also wrap classes that have template parameters. Consider these classes:
1168+
1169+
.. code-block:: cpp
1170+
1171+
struct Cat {};
1172+
struct Dog {};
1173+
1174+
template <typename PetType>
1175+
struct Cage {
1176+
Cage(PetType& pet);
1177+
PetType& get();
1178+
};
1179+
1180+
C++ templates may only be instantiated at compile time, so pybind11 can only
1181+
wrap instantiated templated classes. You cannot wrap a non-instantiated template:
1182+
1183+
.. code-block:: cpp
1184+
1185+
// this will not compile
1186+
py::class_<Cage>(m, "Cage");
1187+
.def("get", &Cage::get);
1188+
1189+
You must explicitly specify each template/type combination that you want to
1190+
wrap separately.
1191+
1192+
.. code-block:: cpp
1193+
1194+
// ok
1195+
py::class_<Cage<Cat>>(m, "CatCage")
1196+
.def("get", &Cage<Cat>::get);
1197+
1198+
// ok
1199+
py::class_<Cage<Dog>>(m, "DogCage")
1200+
.def("get", &Cage<Dog>::get);
1201+
1202+
If your class methods have template parameters you can wrap those as well,
1203+
but once again each instantiation must be explicitly specified:
1204+
1205+
.. code-block:: cpp
1206+
1207+
typename <typename T>
1208+
struct MyClass {
1209+
template <typename V>
1210+
T fn(V v);
1211+
};
1212+
1213+
py::class<MyClass<int>>(m, "MyClassT")
1214+
.def("fn", &MyClass<int>::fn<std::string>);
1215+
11641216
Custom automatic downcasters
11651217
============================
11661218

docs/advanced/functions.rst

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -578,3 +578,37 @@ prefers earlier-defined overloads to later-defined ones.
578578
.. versionadded:: 2.6
579579

580580
The ``py::prepend()`` tag.
581+
582+
Binding functions with template parameters
583+
==========================================
584+
585+
You can bind functions that have template parameters. Here's a function:
586+
587+
.. code-block:: cpp
588+
589+
template <typename T>
590+
void set(T t);
591+
592+
C++ templates cannot be instantiated at runtime, so you cannot bind the
593+
non-instantiated function:
594+
595+
.. code-block:: cpp
596+
597+
// this will not compile
598+
m.def("set", &set);
599+
600+
You must bind each instantiated function template separately. You may bind
601+
each instantiation with the same name, which will be treated the same as
602+
an overloaded function:
603+
604+
.. code-block:: cpp
605+
606+
m.def("set", &set<int>);
607+
m.def("set", &set<std::string>);
608+
609+
Sometimes it's more clear to bind them with separate names, which is also ok:
610+
611+
.. code-block:: cpp
612+
613+
m.def("setInt", &set<int>);
614+
m.def("setString", &set<std::string>);

0 commit comments

Comments
 (0)