0
# STL Integration
1
2
pybind11 provides seamless integration with C++ Standard Template Library (STL) containers, offering both automatic conversion and explicit container binding utilities. This enables efficient data exchange between C++ containers and Python collections.
3
4
## Capabilities
5
6
### Automatic STL Conversions
7
8
Include `<pybind11/stl.h>` for automatic conversion between STL containers and Python collections.
9
10
```cpp { .api }
11
// Automatic conversions (enabled by including pybind11/stl.h)
12
// std::vector<T> <-> Python list
13
// std::array<T, N> <-> Python list
14
// std::list<T> <-> Python list
15
// std::deque<T> <-> Python list
16
// std::set<T> <-> Python set
17
// std::unordered_set<T> <-> Python set
18
// std::map<K, V> <-> Python dict
19
// std::unordered_map<K, V> <-> Python dict
20
// std::pair<T1, T2> <-> Python tuple
21
// std::tuple<Ts...> <-> Python tuple
22
```
23
24
### Explicit Container Binding
25
26
Bind STL containers as Python classes for more control and performance.
27
28
```cpp { .api }
29
// Vector binding
30
template<typename Vector, typename... Options>
31
class_<Vector> bind_vector(module_ &m, const char *name, const Options&... options);
32
33
// Map binding
34
template<typename Map, typename... Options>
35
class_<Map> bind_map(module_ &m, const char *name, const Options&... options);
36
```
37
38
### Container Method Binding
39
40
When using explicit binding, containers get Python-like methods.
41
42
```cpp { .api }
43
// Vector methods (when using bind_vector)
44
class BoundVector {
45
public:
46
// Python list-like interface
47
void append(const T& value);
48
void clear();
49
void extend(const BoundVector& other);
50
void insert(size_t index, const T& value);
51
T pop();
52
T pop(size_t index);
53
void remove(const T& value);
54
55
// Python indexing and slicing
56
T& operator[](size_t index);
57
BoundVector operator[](slice s);
58
59
// Python methods
60
size_t count(const T& value) const;
61
size_t index(const T& value) const;
62
void reverse();
63
void sort();
64
65
// Standard container methods
66
size_t size() const;
67
bool empty() const;
68
iterator begin();
69
iterator end();
70
};
71
72
// Map methods (when using bind_map)
73
class BoundMap {
74
public:
75
// Python dict-like interface
76
void clear();
77
bool contains(const K& key) const;
78
V get(const K& key) const;
79
V get(const K& key, const V& default_value) const;
80
list items() const;
81
list keys() const;
82
V pop(const K& key);
83
V pop(const K& key, const V& default_value);
84
void popitem();
85
void setdefault(const K& key, const V& default_value);
86
void update(const BoundMap& other);
87
list values() const;
88
89
// Python indexing
90
V& operator[](const K& key);
91
92
// Standard container methods
93
size_t size() const;
94
bool empty() const;
95
iterator begin();
96
iterator end();
97
};
98
```
99
100
### Smart Pointer Integration
101
102
STL containers work seamlessly with smart pointers.
103
104
```cpp { .api }
105
// Automatic conversion support for smart pointers in containers
106
// std::vector<std::shared_ptr<T>> <-> Python list
107
// std::vector<std::unique_ptr<T>> <-> Python list (with move semantics)
108
// std::map<K, std::shared_ptr<V>> <-> Python dict
109
```
110
111
### Iterator Support
112
113
Access to STL iterators from Python when using explicit binding.
114
115
```cpp { .api }
116
// Iterator binding (automatically included with container binding)
117
template<typename Iterator>
118
class iterator_wrapper {
119
public:
120
Iterator& operator++();
121
bool operator==(const iterator_wrapper& other) const;
122
bool operator!=(const iterator_wrapper& other) const;
123
auto operator*() const;
124
};
125
```
126
127
### Optional and Variant Support
128
129
Support for C++17 optional and variant types.
130
131
```cpp { .api }
132
// std::optional<T> support (include pybind11/stl.h)
133
// Converts to Python None or the contained value
134
135
// std::variant<Ts...> support
136
// Automatically selects appropriate Python type based on active variant member
137
```
138
139
## Usage Examples
140
141
### Automatic STL Conversion
142
143
```cpp
144
#include <pybind11/pybind11.h>
145
#include <pybind11/stl.h>
146
#include <vector>
147
#include <map>
148
149
namespace py = pybind11;
150
151
std::vector<int> create_vector() {
152
return {1, 2, 3, 4, 5};
153
}
154
155
void process_vector(const std::vector<std::string>& vec) {
156
for (const auto& item : vec) {
157
std::cout << item << std::endl;
158
}
159
}
160
161
std::map<std::string, int> create_map() {
162
return {{"apple", 5}, {"banana", 3}, {"orange", 8}};
163
}
164
165
PYBIND11_MODULE(example, m) {
166
// Automatic conversion - vectors become Python lists
167
m.def("create_vector", &create_vector);
168
m.def("process_vector", &process_vector);
169
170
// Automatic conversion - maps become Python dicts
171
m.def("create_map", &create_map);
172
}
173
```
174
175
### Explicit Container Binding
176
177
```cpp
178
#include <pybind11/pybind11.h>
179
#include <pybind11/stl_bind.h>
180
#include <vector>
181
182
namespace py = pybind11;
183
184
PYBIND11_MODULE(example, m) {
185
// Bind vector as a Python class
186
py::bind_vector<std::vector<int>>(m, "VectorInt");
187
py::bind_vector<std::vector<std::string>>(m, "VectorString");
188
189
// Bind map as a Python class
190
py::bind_map<std::map<std::string, int>>(m, "MapStringInt");
191
192
// Custom container with additional methods
193
py::class_<std::vector<double>>(m, "VectorDouble")
194
.def(py::init<>())
195
.def("push_back", &std::vector<double>::push_back)
196
.def("size", &std::vector<double>::size)
197
.def("__len__", &std::vector<double>::size)
198
.def("__iter__", [](const std::vector<double> &v) {
199
return py::make_iterator(v.begin(), v.end());
200
}, py::keep_alive<0, 1>());
201
}
202
```
203
204
### Working with Nested Containers
205
206
```cpp
207
#include <pybind11/pybind11.h>
208
#include <pybind11/stl.h>
209
210
namespace py = pybind11;
211
212
// Nested container function
213
std::vector<std::vector<int>> create_matrix(int rows, int cols) {
214
std::vector<std::vector<int>> matrix(rows, std::vector<int>(cols, 0));
215
for (int i = 0; i < rows; ++i) {
216
for (int j = 0; j < cols; ++j) {
217
matrix[i][j] = i * cols + j;
218
}
219
}
220
return matrix;
221
}
222
223
// Complex nested structure
224
std::map<std::string, std::vector<std::pair<int, double>>> complex_data() {
225
return {
226
{"series1", {{1, 1.1}, {2, 2.2}, {3, 3.3}}},
227
{"series2", {{10, 10.1}, {20, 20.2}, {30, 30.3}}}
228
};
229
}
230
231
PYBIND11_MODULE(example, m) {
232
m.def("create_matrix", &create_matrix);
233
m.def("complex_data", &complex_data);
234
}
235
```
236
237
### Smart Pointer Containers
238
239
```cpp
240
#include <pybind11/pybind11.h>
241
#include <pybind11/stl.h>
242
#include <memory>
243
#include <vector>
244
245
namespace py = pybind11;
246
247
class Widget {
248
public:
249
Widget(const std::string& name) : name_(name) {}
250
const std::string& name() const { return name_; }
251
private:
252
std::string name_;
253
};
254
255
std::vector<std::shared_ptr<Widget>> create_widgets() {
256
return {
257
std::make_shared<Widget>("widget1"),
258
std::make_shared<Widget>("widget2"),
259
std::make_shared<Widget>("widget3")
260
};
261
}
262
263
PYBIND11_MODULE(example, m) {
264
py::class_<Widget>(m, "Widget")
265
.def(py::init<const std::string&>())
266
.def("name", &Widget::name);
267
268
// Automatic conversion of vector of shared_ptr
269
m.def("create_widgets", &create_widgets);
270
}
271
```
272
273
### Custom Iterator Example
274
275
```cpp
276
#include <pybind11/pybind11.h>
277
#include <pybind11/stl.h>
278
279
namespace py = pybind11;
280
281
class NumberGenerator {
282
int current_, max_;
283
public:
284
NumberGenerator(int max) : current_(0), max_(max) {}
285
286
// Make it iterable
287
NumberGenerator& iter() { return *this; }
288
int next() {
289
if (current_ >= max_) throw py::stop_iteration();
290
return current_++;
291
}
292
};
293
294
PYBIND11_MODULE(example, m) {
295
py::class_<NumberGenerator>(m, "NumberGenerator")
296
.def(py::init<int>())
297
.def("__iter__", &NumberGenerator::iter,
298
py::return_value_policy::reference_internal)
299
.def("__next__", &NumberGenerator::next);
300
}
301
```
302
303
## Performance Considerations
304
305
### Automatic vs Explicit Binding
306
307
```cpp
308
// Automatic conversion (pybind11/stl.h)
309
// Pros: Simple, works out of the box
310
// Cons: Always copies data, memory overhead
311
312
std::vector<int> get_data() { return large_vector; } // Always copies
313
314
// Explicit binding (pybind11/stl_bind.h)
315
// Pros: Direct access, no copying, Python-like interface
316
// Cons: More setup required
317
318
py::bind_vector<std::vector<int>>(m, "VectorInt"); // Direct access
319
```
320
321
### Return Value Policies with Containers
322
323
```cpp
324
class DataManager {
325
std::vector<double> data_;
326
public:
327
// Return reference to avoid copying
328
const std::vector<double>& get_data() const { return data_; }
329
std::vector<double>& get_mutable_data() { return data_; }
330
};
331
332
PYBIND11_MODULE(example, m) {
333
py::class_<DataManager>(m, "DataManager")
334
.def("get_data", &DataManager::get_data,
335
py::return_value_policy::reference_internal)
336
.def("get_mutable_data", &DataManager::get_mutable_data,
337
py::return_value_policy::reference_internal);
338
}
339
```
340
341
## Types
342
343
```cpp { .api }
344
namespace pybind11 {
345
// Container binding functions (from stl_bind.h)
346
template<typename Vector, typename... Options>
347
class_<Vector> bind_vector(module_ &m, const char *name, const Options&... options);
348
349
template<typename Map, typename... Options>
350
class_<Map> bind_map(module_ &m, const char *name, const Options&... options);
351
352
template<typename Deque, typename... Options>
353
class_<Deque> bind_deque(module_ &m, const char *name, const Options&... options);
354
355
// Iterator utilities
356
template<typename Iterator>
357
class iterator_wrapper;
358
359
template<typename Iterator>
360
auto make_iterator(Iterator first, Iterator last);
361
362
template<typename Iterator>
363
auto make_key_iterator(Iterator first, Iterator last);
364
365
template<typename Iterator>
366
auto make_value_iterator(Iterator first, Iterator last);
367
}
368
```