stl_bind.h revision 12037:d28054ac6ec9
1/* 2 pybind11/std_bind.h: Binding generators for STL data types 3 4 Copyright (c) 2016 Sergey Lyskov and Wenzel Jakob 5 6 All rights reserved. Use of this source code is governed by a 7 BSD-style license that can be found in the LICENSE file. 8*/ 9 10#pragma once 11 12#include "common.h" 13#include "operators.h" 14 15#include <algorithm> 16#include <sstream> 17 18NAMESPACE_BEGIN(pybind11) 19NAMESPACE_BEGIN(detail) 20 21/* SFINAE helper class used by 'is_comparable */ 22template <typename T> struct container_traits { 23 template <typename T2> static std::true_type test_comparable(decltype(std::declval<const T2 &>() == std::declval<const T2 &>())*); 24 template <typename T2> static std::false_type test_comparable(...); 25 template <typename T2> static std::true_type test_value(typename T2::value_type *); 26 template <typename T2> static std::false_type test_value(...); 27 template <typename T2> static std::true_type test_pair(typename T2::first_type *, typename T2::second_type *); 28 template <typename T2> static std::false_type test_pair(...); 29 30 static constexpr const bool is_comparable = std::is_same<std::true_type, decltype(test_comparable<T>(nullptr))>::value; 31 static constexpr const bool is_pair = std::is_same<std::true_type, decltype(test_pair<T>(nullptr, nullptr))>::value; 32 static constexpr const bool is_vector = std::is_same<std::true_type, decltype(test_value<T>(nullptr))>::value; 33 static constexpr const bool is_element = !is_pair && !is_vector; 34}; 35 36/* Default: is_comparable -> std::false_type */ 37template <typename T, typename SFINAE = void> 38struct is_comparable : std::false_type { }; 39 40/* For non-map data structures, check whether operator== can be instantiated */ 41template <typename T> 42struct is_comparable< 43 T, enable_if_t<container_traits<T>::is_element && 44 container_traits<T>::is_comparable>> 45 : std::true_type { }; 46 47/* For a vector/map data structure, recursively check the value type (which is std::pair for maps) */ 48template <typename T> 49struct is_comparable<T, enable_if_t<container_traits<T>::is_vector>> { 50 static constexpr const bool value = 51 is_comparable<typename T::value_type>::value; 52}; 53 54/* For pairs, recursively check the two data types */ 55template <typename T> 56struct is_comparable<T, enable_if_t<container_traits<T>::is_pair>> { 57 static constexpr const bool value = 58 is_comparable<typename T::first_type>::value && 59 is_comparable<typename T::second_type>::value; 60}; 61 62/* Fallback functions */ 63template <typename, typename, typename... Args> void vector_if_copy_constructible(const Args &...) { } 64template <typename, typename, typename... Args> void vector_if_equal_operator(const Args &...) { } 65template <typename, typename, typename... Args> void vector_if_insertion_operator(const Args &...) { } 66template <typename, typename, typename... Args> void vector_modifiers(const Args &...) { } 67 68template<typename Vector, typename Class_> 69void vector_if_copy_constructible(enable_if_t< 70 std::is_copy_constructible<Vector>::value && 71 std::is_copy_constructible<typename Vector::value_type>::value, Class_> &cl) { 72 73 cl.def(init<const Vector &>(), "Copy constructor"); 74} 75 76template<typename Vector, typename Class_> 77void vector_if_equal_operator(enable_if_t<is_comparable<Vector>::value, Class_> &cl) { 78 using T = typename Vector::value_type; 79 80 cl.def(self == self); 81 cl.def(self != self); 82 83 cl.def("count", 84 [](const Vector &v, const T &x) { 85 return std::count(v.begin(), v.end(), x); 86 }, 87 arg("x"), 88 "Return the number of times ``x`` appears in the list" 89 ); 90 91 cl.def("remove", [](Vector &v, const T &x) { 92 auto p = std::find(v.begin(), v.end(), x); 93 if (p != v.end()) 94 v.erase(p); 95 else 96 throw value_error(); 97 }, 98 arg("x"), 99 "Remove the first item from the list whose value is x. " 100 "It is an error if there is no such item." 101 ); 102 103 cl.def("__contains__", 104 [](const Vector &v, const T &x) { 105 return std::find(v.begin(), v.end(), x) != v.end(); 106 }, 107 arg("x"), 108 "Return true the container contains ``x``" 109 ); 110} 111 112// Vector modifiers -- requires a copyable vector_type: 113// (Technically, some of these (pop and __delitem__) don't actually require copyability, but it seems 114// silly to allow deletion but not insertion, so include them here too.) 115template <typename Vector, typename Class_> 116void vector_modifiers(enable_if_t<std::is_copy_constructible<typename Vector::value_type>::value, Class_> &cl) { 117 using T = typename Vector::value_type; 118 using SizeType = typename Vector::size_type; 119 using DiffType = typename Vector::difference_type; 120 121 cl.def("append", 122 [](Vector &v, const T &value) { v.push_back(value); }, 123 arg("x"), 124 "Add an item to the end of the list"); 125 126 cl.def("__init__", [](Vector &v, iterable it) { 127 new (&v) Vector(); 128 try { 129 v.reserve(len(it)); 130 for (handle h : it) 131 v.push_back(h.cast<T>()); 132 } catch (...) { 133 v.~Vector(); 134 throw; 135 } 136 }); 137 138 cl.def("extend", 139 [](Vector &v, const Vector &src) { 140 v.reserve(v.size() + src.size()); 141 v.insert(v.end(), src.begin(), src.end()); 142 }, 143 arg("L"), 144 "Extend the list by appending all the items in the given list" 145 ); 146 147 cl.def("insert", 148 [](Vector &v, SizeType i, const T &x) { 149 v.insert(v.begin() + (DiffType) i, x); 150 }, 151 arg("i") , arg("x"), 152 "Insert an item at a given position." 153 ); 154 155 cl.def("pop", 156 [](Vector &v) { 157 if (v.empty()) 158 throw index_error(); 159 T t = v.back(); 160 v.pop_back(); 161 return t; 162 }, 163 "Remove and return the last item" 164 ); 165 166 cl.def("pop", 167 [](Vector &v, SizeType i) { 168 if (i >= v.size()) 169 throw index_error(); 170 T t = v[i]; 171 v.erase(v.begin() + (DiffType) i); 172 return t; 173 }, 174 arg("i"), 175 "Remove and return the item at index ``i``" 176 ); 177 178 cl.def("__setitem__", 179 [](Vector &v, SizeType i, const T &t) { 180 if (i >= v.size()) 181 throw index_error(); 182 v[i] = t; 183 } 184 ); 185 186 /// Slicing protocol 187 cl.def("__getitem__", 188 [](const Vector &v, slice slice) -> Vector * { 189 size_t start, stop, step, slicelength; 190 191 if (!slice.compute(v.size(), &start, &stop, &step, &slicelength)) 192 throw error_already_set(); 193 194 Vector *seq = new Vector(); 195 seq->reserve((size_t) slicelength); 196 197 for (size_t i=0; i<slicelength; ++i) { 198 seq->push_back(v[start]); 199 start += step; 200 } 201 return seq; 202 }, 203 arg("s"), 204 "Retrieve list elements using a slice object" 205 ); 206 207 cl.def("__setitem__", 208 [](Vector &v, slice slice, const Vector &value) { 209 size_t start, stop, step, slicelength; 210 if (!slice.compute(v.size(), &start, &stop, &step, &slicelength)) 211 throw error_already_set(); 212 213 if (slicelength != value.size()) 214 throw std::runtime_error("Left and right hand size of slice assignment have different sizes!"); 215 216 for (size_t i=0; i<slicelength; ++i) { 217 v[start] = value[i]; 218 start += step; 219 } 220 }, 221 "Assign list elements using a slice object" 222 ); 223 224 cl.def("__delitem__", 225 [](Vector &v, SizeType i) { 226 if (i >= v.size()) 227 throw index_error(); 228 v.erase(v.begin() + DiffType(i)); 229 }, 230 "Delete the list elements at index ``i``" 231 ); 232 233 cl.def("__delitem__", 234 [](Vector &v, slice slice) { 235 size_t start, stop, step, slicelength; 236 237 if (!slice.compute(v.size(), &start, &stop, &step, &slicelength)) 238 throw error_already_set(); 239 240 if (step == 1 && false) { 241 v.erase(v.begin() + (DiffType) start, v.begin() + DiffType(start + slicelength)); 242 } else { 243 for (size_t i = 0; i < slicelength; ++i) { 244 v.erase(v.begin() + DiffType(start)); 245 start += step - 1; 246 } 247 } 248 }, 249 "Delete list elements using a slice object" 250 ); 251 252} 253 254// If the type has an operator[] that doesn't return a reference (most notably std::vector<bool>), 255// we have to access by copying; otherwise we return by reference. 256template <typename Vector> using vector_needs_copy = negation< 257 std::is_same<decltype(std::declval<Vector>()[typename Vector::size_type()]), typename Vector::value_type &>>; 258 259// The usual case: access and iterate by reference 260template <typename Vector, typename Class_> 261void vector_accessor(enable_if_t<!vector_needs_copy<Vector>::value, Class_> &cl) { 262 using T = typename Vector::value_type; 263 using SizeType = typename Vector::size_type; 264 using ItType = typename Vector::iterator; 265 266 cl.def("__getitem__", 267 [](Vector &v, SizeType i) -> T & { 268 if (i >= v.size()) 269 throw index_error(); 270 return v[i]; 271 }, 272 return_value_policy::reference_internal // ref + keepalive 273 ); 274 275 cl.def("__iter__", 276 [](Vector &v) { 277 return make_iterator< 278 return_value_policy::reference_internal, ItType, ItType, T&>( 279 v.begin(), v.end()); 280 }, 281 keep_alive<0, 1>() /* Essential: keep list alive while iterator exists */ 282 ); 283} 284 285// The case for special objects, like std::vector<bool>, that have to be returned-by-copy: 286template <typename Vector, typename Class_> 287void vector_accessor(enable_if_t<vector_needs_copy<Vector>::value, Class_> &cl) { 288 using T = typename Vector::value_type; 289 using SizeType = typename Vector::size_type; 290 using ItType = typename Vector::iterator; 291 cl.def("__getitem__", 292 [](const Vector &v, SizeType i) -> T { 293 if (i >= v.size()) 294 throw index_error(); 295 return v[i]; 296 } 297 ); 298 299 cl.def("__iter__", 300 [](Vector &v) { 301 return make_iterator< 302 return_value_policy::copy, ItType, ItType, T>( 303 v.begin(), v.end()); 304 }, 305 keep_alive<0, 1>() /* Essential: keep list alive while iterator exists */ 306 ); 307} 308 309template <typename Vector, typename Class_> auto vector_if_insertion_operator(Class_ &cl, std::string const &name) 310 -> decltype(std::declval<std::ostream&>() << std::declval<typename Vector::value_type>(), void()) { 311 using size_type = typename Vector::size_type; 312 313 cl.def("__repr__", 314 [name](Vector &v) { 315 std::ostringstream s; 316 s << name << '['; 317 for (size_type i=0; i < v.size(); ++i) { 318 s << v[i]; 319 if (i != v.size() - 1) 320 s << ", "; 321 } 322 s << ']'; 323 return s.str(); 324 }, 325 "Return the canonical string representation of this list." 326 ); 327} 328 329// Provide the buffer interface for vectors if we have data() and we have a format for it 330// GCC seems to have "void std::vector<bool>::data()" - doing SFINAE on the existence of data() is insufficient, we need to check it returns an appropriate pointer 331template <typename Vector, typename = void> 332struct vector_has_data_and_format : std::false_type {}; 333template <typename Vector> 334struct vector_has_data_and_format<Vector, enable_if_t<std::is_same<decltype(format_descriptor<typename Vector::value_type>::format(), std::declval<Vector>().data()), typename Vector::value_type*>::value>> : std::true_type {}; 335 336// Add the buffer interface to a vector 337template <typename Vector, typename Class_, typename... Args> 338enable_if_t<detail::any_of<std::is_same<Args, buffer_protocol>...>::value> 339vector_buffer(Class_& cl) { 340 using T = typename Vector::value_type; 341 342 static_assert(vector_has_data_and_format<Vector>::value, "There is not an appropriate format descriptor for this vector"); 343 344 // numpy.h declares this for arbitrary types, but it may raise an exception and crash hard at runtime if PYBIND11_NUMPY_DTYPE hasn't been called, so check here 345 format_descriptor<T>::format(); 346 347 cl.def_buffer([](Vector& v) -> buffer_info { 348 return buffer_info(v.data(), sizeof(T), format_descriptor<T>::format(), 1, {v.size()}, {sizeof(T)}); 349 }); 350 351 cl.def("__init__", [](Vector& vec, buffer buf) { 352 auto info = buf.request(); 353 if (info.ndim != 1 || info.strides[0] <= 0 || info.strides[0] % sizeof(T)) 354 throw type_error("Only valid 1D buffers can be copied to a vector"); 355 if (!detail::compare_buffer_info<T>::compare(info) || sizeof(T) != info.itemsize) 356 throw type_error("Format mismatch (Python: " + info.format + " C++: " + format_descriptor<T>::format() + ")"); 357 new (&vec) Vector(); 358 vec.reserve(info.shape[0]); 359 T *p = static_cast<T*>(info.ptr); 360 auto step = info.strides[0] / sizeof(T); 361 T *end = p + info.shape[0] * step; 362 for (; p < end; p += step) 363 vec.push_back(*p); 364 }); 365 366 return; 367} 368 369template <typename Vector, typename Class_, typename... Args> 370enable_if_t<!detail::any_of<std::is_same<Args, buffer_protocol>...>::value> vector_buffer(Class_&) {} 371 372NAMESPACE_END(detail) 373 374// 375// std::vector 376// 377template <typename Vector, typename holder_type = std::unique_ptr<Vector>, typename... Args> 378class_<Vector, holder_type> bind_vector(module &m, std::string const &name, Args&&... args) { 379 using Class_ = class_<Vector, holder_type>; 380 381 Class_ cl(m, name.c_str(), std::forward<Args>(args)...); 382 383 // Declare the buffer interface if a buffer_protocol() is passed in 384 detail::vector_buffer<Vector, Class_, Args...>(cl); 385 386 cl.def(init<>()); 387 388 // Register copy constructor (if possible) 389 detail::vector_if_copy_constructible<Vector, Class_>(cl); 390 391 // Register comparison-related operators and functions (if possible) 392 detail::vector_if_equal_operator<Vector, Class_>(cl); 393 394 // Register stream insertion operator (if possible) 395 detail::vector_if_insertion_operator<Vector, Class_>(cl, name); 396 397 // Modifiers require copyable vector value type 398 detail::vector_modifiers<Vector, Class_>(cl); 399 400 // Accessor and iterator; return by value if copyable, otherwise we return by ref + keep-alive 401 detail::vector_accessor<Vector, Class_>(cl); 402 403 cl.def("__bool__", 404 [](const Vector &v) -> bool { 405 return !v.empty(); 406 }, 407 "Check whether the list is nonempty" 408 ); 409 410 cl.def("__len__", &Vector::size); 411 412 413 414 415#if 0 416 // C++ style functions deprecated, leaving it here as an example 417 cl.def(init<size_type>()); 418 419 cl.def("resize", 420 (void (Vector::*) (size_type count)) & Vector::resize, 421 "changes the number of elements stored"); 422 423 cl.def("erase", 424 [](Vector &v, SizeType i) { 425 if (i >= v.size()) 426 throw index_error(); 427 v.erase(v.begin() + i); 428 }, "erases element at index ``i``"); 429 430 cl.def("empty", &Vector::empty, "checks whether the container is empty"); 431 cl.def("size", &Vector::size, "returns the number of elements"); 432 cl.def("push_back", (void (Vector::*)(const T&)) &Vector::push_back, "adds an element to the end"); 433 cl.def("pop_back", &Vector::pop_back, "removes the last element"); 434 435 cl.def("max_size", &Vector::max_size, "returns the maximum possible number of elements"); 436 cl.def("reserve", &Vector::reserve, "reserves storage"); 437 cl.def("capacity", &Vector::capacity, "returns the number of elements that can be held in currently allocated storage"); 438 cl.def("shrink_to_fit", &Vector::shrink_to_fit, "reduces memory usage by freeing unused memory"); 439 440 cl.def("clear", &Vector::clear, "clears the contents"); 441 cl.def("swap", &Vector::swap, "swaps the contents"); 442 443 cl.def("front", [](Vector &v) { 444 if (v.size()) return v.front(); 445 else throw index_error(); 446 }, "access the first element"); 447 448 cl.def("back", [](Vector &v) { 449 if (v.size()) return v.back(); 450 else throw index_error(); 451 }, "access the last element "); 452 453#endif 454 455 return cl; 456} 457 458 459 460// 461// std::map, std::unordered_map 462// 463 464NAMESPACE_BEGIN(detail) 465 466/* Fallback functions */ 467template <typename, typename, typename... Args> void map_if_insertion_operator(const Args &...) { } 468template <typename, typename, typename... Args> void map_assignment(const Args &...) { } 469 470// Map assignment when copy-assignable: just copy the value 471template <typename Map, typename Class_> 472void map_assignment(enable_if_t<std::is_copy_assignable<typename Map::mapped_type>::value, Class_> &cl) { 473 using KeyType = typename Map::key_type; 474 using MappedType = typename Map::mapped_type; 475 476 cl.def("__setitem__", 477 [](Map &m, const KeyType &k, const MappedType &v) { 478 auto it = m.find(k); 479 if (it != m.end()) it->second = v; 480 else m.emplace(k, v); 481 } 482 ); 483} 484 485// Not copy-assignable, but still copy-constructible: we can update the value by erasing and reinserting 486template<typename Map, typename Class_> 487void map_assignment(enable_if_t< 488 !std::is_copy_assignable<typename Map::mapped_type>::value && 489 std::is_copy_constructible<typename Map::mapped_type>::value, 490 Class_> &cl) { 491 using KeyType = typename Map::key_type; 492 using MappedType = typename Map::mapped_type; 493 494 cl.def("__setitem__", 495 [](Map &m, const KeyType &k, const MappedType &v) { 496 // We can't use m[k] = v; because value type might not be default constructable 497 auto r = m.emplace(k, v); 498 if (!r.second) { 499 // value type is not copy assignable so the only way to insert it is to erase it first... 500 m.erase(r.first); 501 m.emplace(k, v); 502 } 503 } 504 ); 505} 506 507 508template <typename Map, typename Class_> auto map_if_insertion_operator(Class_ &cl, std::string const &name) 509-> decltype(std::declval<std::ostream&>() << std::declval<typename Map::key_type>() << std::declval<typename Map::mapped_type>(), void()) { 510 511 cl.def("__repr__", 512 [name](Map &m) { 513 std::ostringstream s; 514 s << name << '{'; 515 bool f = false; 516 for (auto const &kv : m) { 517 if (f) 518 s << ", "; 519 s << kv.first << ": " << kv.second; 520 f = true; 521 } 522 s << '}'; 523 return s.str(); 524 }, 525 "Return the canonical string representation of this map." 526 ); 527} 528 529 530NAMESPACE_END(detail) 531 532template <typename Map, typename holder_type = std::unique_ptr<Map>, typename... Args> 533class_<Map, holder_type> bind_map(module &m, const std::string &name, Args&&... args) { 534 using KeyType = typename Map::key_type; 535 using MappedType = typename Map::mapped_type; 536 using Class_ = class_<Map, holder_type>; 537 538 Class_ cl(m, name.c_str(), std::forward<Args>(args)...); 539 540 cl.def(init<>()); 541 542 // Register stream insertion operator (if possible) 543 detail::map_if_insertion_operator<Map, Class_>(cl, name); 544 545 cl.def("__bool__", 546 [](const Map &m) -> bool { return !m.empty(); }, 547 "Check whether the map is nonempty" 548 ); 549 550 cl.def("__iter__", 551 [](Map &m) { return make_key_iterator(m.begin(), m.end()); }, 552 keep_alive<0, 1>() /* Essential: keep list alive while iterator exists */ 553 ); 554 555 cl.def("items", 556 [](Map &m) { return make_iterator(m.begin(), m.end()); }, 557 keep_alive<0, 1>() /* Essential: keep list alive while iterator exists */ 558 ); 559 560 cl.def("__getitem__", 561 [](Map &m, const KeyType &k) -> MappedType & { 562 auto it = m.find(k); 563 if (it == m.end()) 564 throw key_error(); 565 return it->second; 566 }, 567 return_value_policy::reference_internal // ref + keepalive 568 ); 569 570 // Assignment provided only if the type is copyable 571 detail::map_assignment<Map, Class_>(cl); 572 573 cl.def("__delitem__", 574 [](Map &m, const KeyType &k) { 575 auto it = m.find(k); 576 if (it == m.end()) 577 throw key_error(); 578 return m.erase(it); 579 } 580 ); 581 582 cl.def("__len__", &Map::size); 583 584 return cl; 585} 586 587NAMESPACE_END(pybind11) 588