summaryrefslogtreecommitdiff
path: root/ext/pybind11/include/pybind11/stl_bind.h
diff options
context:
space:
mode:
Diffstat (limited to 'ext/pybind11/include/pybind11/stl_bind.h')
-rw-r--r--ext/pybind11/include/pybind11/stl_bind.h82
1 files changed, 47 insertions, 35 deletions
diff --git a/ext/pybind11/include/pybind11/stl_bind.h b/ext/pybind11/include/pybind11/stl_bind.h
index 897188220..7ef687878 100644
--- a/ext/pybind11/include/pybind11/stl_bind.h
+++ b/ext/pybind11/include/pybind11/stl_bind.h
@@ -9,13 +9,13 @@
#pragma once
-#include "common.h"
+#include "detail/common.h"
#include "operators.h"
#include <algorithm>
#include <sstream>
-NAMESPACE_BEGIN(pybind11)
+NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
NAMESPACE_BEGIN(detail)
/* SFINAE helper class used by 'is_comparable */
@@ -66,10 +66,7 @@ template <typename, typename, typename... Args> void vector_if_insertion_operato
template <typename, typename, typename... Args> void vector_modifiers(const Args &...) { }
template<typename Vector, typename Class_>
-void vector_if_copy_constructible(enable_if_t<
- std::is_copy_constructible<Vector>::value &&
- std::is_copy_constructible<typename Vector::value_type>::value, Class_> &cl) {
-
+void vector_if_copy_constructible(enable_if_t<is_copy_constructible<Vector>::value, Class_> &cl) {
cl.def(init<const Vector &>(), "Copy constructor");
}
@@ -113,7 +110,7 @@ void vector_if_equal_operator(enable_if_t<is_comparable<Vector>::value, Class_>
// (Technically, some of these (pop and __delitem__) don't actually require copyability, but it seems
// silly to allow deletion but not insertion, so include them here too.)
template <typename Vector, typename Class_>
-void vector_modifiers(enable_if_t<std::is_copy_constructible<typename Vector::value_type>::value, Class_> &cl) {
+void vector_modifiers(enable_if_t<is_copy_constructible<typename Vector::value_type>::value, Class_> &cl) {
using T = typename Vector::value_type;
using SizeType = typename Vector::size_type;
using DiffType = typename Vector::difference_type;
@@ -123,21 +120,16 @@ void vector_modifiers(enable_if_t<std::is_copy_constructible<typename Vector::va
arg("x"),
"Add an item to the end of the list");
- cl.def("__init__", [](Vector &v, iterable it) {
- new (&v) Vector();
- try {
- v.reserve(len(it));
- for (handle h : it)
- v.push_back(h.cast<T>());
- } catch (...) {
- v.~Vector();
- throw;
- }
- });
+ cl.def(init([](iterable it) {
+ auto v = std::unique_ptr<Vector>(new Vector());
+ v->reserve(len(it));
+ for (handle h : it)
+ v->push_back(h.cast<T>());
+ return v.release();
+ }));
cl.def("extend",
[](Vector &v, const Vector &src) {
- v.reserve(v.size() + src.size());
v.insert(v.end(), src.begin(), src.end());
},
arg("L"),
@@ -146,6 +138,8 @@ void vector_modifiers(enable_if_t<std::is_copy_constructible<typename Vector::va
cl.def("insert",
[](Vector &v, SizeType i, const T &x) {
+ if (i > v.size())
+ throw index_error();
v.insert(v.begin() + (DiffType) i, x);
},
arg("i") , arg("x"),
@@ -345,23 +339,25 @@ vector_buffer(Class_& cl) {
format_descriptor<T>::format();
cl.def_buffer([](Vector& v) -> buffer_info {
- return buffer_info(v.data(), sizeof(T), format_descriptor<T>::format(), 1, {v.size()}, {sizeof(T)});
+ return buffer_info(v.data(), static_cast<ssize_t>(sizeof(T)), format_descriptor<T>::format(), 1, {v.size()}, {sizeof(T)});
});
- cl.def("__init__", [](Vector& vec, buffer buf) {
+ cl.def(init([](buffer buf) {
auto info = buf.request();
- if (info.ndim != 1 || info.strides[0] <= 0 || info.strides[0] % sizeof(T))
+ if (info.ndim != 1 || info.strides[0] % static_cast<ssize_t>(sizeof(T)))
throw type_error("Only valid 1D buffers can be copied to a vector");
- if (!detail::compare_buffer_info<T>::compare(info) || sizeof(T) != info.itemsize)
+ if (!detail::compare_buffer_info<T>::compare(info) || (ssize_t) sizeof(T) != info.itemsize)
throw type_error("Format mismatch (Python: " + info.format + " C++: " + format_descriptor<T>::format() + ")");
- new (&vec) Vector();
- vec.reserve(info.shape[0]);
+
+ auto vec = std::unique_ptr<Vector>(new Vector());
+ vec->reserve((size_t) info.shape[0]);
T *p = static_cast<T*>(info.ptr);
- auto step = info.strides[0] / sizeof(T);
+ ssize_t step = info.strides[0] / static_cast<ssize_t>(sizeof(T));
T *end = p + info.shape[0] * step;
- for (; p < end; p += step)
- vec.push_back(*p);
- });
+ for (; p != end; p += step)
+ vec->push_back(*p);
+ return vec.release();
+ }));
return;
}
@@ -375,10 +371,16 @@ NAMESPACE_END(detail)
// std::vector
//
template <typename Vector, typename holder_type = std::unique_ptr<Vector>, typename... Args>
-class_<Vector, holder_type> bind_vector(module &m, std::string const &name, Args&&... args) {
+class_<Vector, holder_type> bind_vector(handle scope, std::string const &name, Args&&... args) {
using Class_ = class_<Vector, holder_type>;
- Class_ cl(m, name.c_str(), std::forward<Args>(args)...);
+ // If the value_type is unregistered (e.g. a converting type) or is itself registered
+ // module-local then make the vector binding module-local as well:
+ using vtype = typename Vector::value_type;
+ auto vtype_info = detail::get_type_info(typeid(vtype));
+ bool local = !vtype_info || vtype_info->module_local;
+
+ Class_ cl(scope, name.c_str(), pybind11::module_local(local), std::forward<Args>(args)...);
// Declare the buffer interface if a buffer_protocol() is passed in
detail::vector_buffer<Vector, Class_, Args...>(cl);
@@ -486,7 +488,7 @@ void map_assignment(enable_if_t<std::is_copy_assignable<typename Map::mapped_typ
template<typename Map, typename Class_>
void map_assignment(enable_if_t<
!std::is_copy_assignable<typename Map::mapped_type>::value &&
- std::is_copy_constructible<typename Map::mapped_type>::value,
+ is_copy_constructible<typename Map::mapped_type>::value,
Class_> &cl) {
using KeyType = typename Map::key_type;
using MappedType = typename Map::mapped_type;
@@ -530,12 +532,22 @@ template <typename Map, typename Class_> auto map_if_insertion_operator(Class_ &
NAMESPACE_END(detail)
template <typename Map, typename holder_type = std::unique_ptr<Map>, typename... Args>
-class_<Map, holder_type> bind_map(module &m, const std::string &name, Args&&... args) {
+class_<Map, holder_type> bind_map(handle scope, const std::string &name, Args&&... args) {
using KeyType = typename Map::key_type;
using MappedType = typename Map::mapped_type;
using Class_ = class_<Map, holder_type>;
- Class_ cl(m, name.c_str(), std::forward<Args>(args)...);
+ // If either type is a non-module-local bound type then make the map binding non-local as well;
+ // otherwise (e.g. both types are either module-local or converting) the map will be
+ // module-local.
+ auto tinfo = detail::get_type_info(typeid(MappedType));
+ bool local = !tinfo || tinfo->module_local;
+ if (local) {
+ tinfo = detail::get_type_info(typeid(KeyType));
+ local = !tinfo || tinfo->module_local;
+ }
+
+ Class_ cl(scope, name.c_str(), pybind11::module_local(local), std::forward<Args>(args)...);
cl.def(init<>());
@@ -584,4 +596,4 @@ class_<Map, holder_type> bind_map(module &m, const std::string &name, Args&&...
return cl;
}
-NAMESPACE_END(pybind11)
+NAMESPACE_END(PYBIND11_NAMESPACE)