or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

advanced-features.mdcore-binding.mdexception-handling.mdindex.mdnumpy-integration.mdpython-package.mdstl-integration.mdtype-system.md

stl-integration.mddocs/

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

```