3
3
#include < string>
4
4
#include < numpy/arrayobject.h>
5
5
6
+ #include " ../traits.hpp"
6
7
#include " ../macros.hpp"
7
8
#include " ../numpy_proxy.hpp"
8
9
9
10
namespace cpp2py {
10
11
11
- template <typename T> static void delete_pycapsule (PyObject *capsule) {
12
- auto *ptr = static_cast <std::unique_ptr<T[]> *>(PyCapsule_GetPointer (capsule, " guard" ));
13
- delete ptr;
14
- }
15
-
16
12
// Convert vector to numpy_proxy, WARNING: Deep Copy
17
- template <typename T> numpy_proxy make_numpy_proxy_from_vector (std::vector<T> const &v) {
13
+ template <typename V> numpy_proxy make_numpy_proxy_from_vector (V &&v) {
14
+ static_assert (is_instantiation_of_v<std::vector, std::decay_t <V>>, " Logic error" );
15
+ using value_type = typename std::remove_reference_t <V>::value_type;
18
16
19
- auto *data_ptr = new std::unique_ptr<T[]>{new T[v.size ()]};
20
- std::copy (begin (v), end (v), data_ptr->get ());
21
- auto capsule = PyCapsule_New (data_ptr, " guard" , &delete_pycapsule<T>);
17
+ auto *vec_heap = new std::vector<value_type>{std::forward<V>(v)};
18
+ auto delete_pycapsule = [](PyObject *capsule) {
19
+ auto *ptr = static_cast <std::vector<value_type> *>(PyCapsule_GetPointer (capsule, " guard" ));
20
+ delete ptr;
21
+ };
22
+ PyObject *capsule = PyCapsule_New (vec_heap, " guard" , delete_pycapsule);
22
23
23
24
return {1 , // rank
24
- npy_type<std:: remove_const_t <T> >,
25
- (void *)data_ptr-> get (),
26
- std::is_const_v<T >,
27
- v_t { static_cast <long >(v. size ())}, // extents
28
- v_t {sizeof (T )}, // strides
25
+ npy_type<value_type >,
26
+ (void *)vec_heap-> data (),
27
+ std::is_const_v<value_type >,
28
+ std::vector <long >{ long (vec_heap-> size ())}, // extents
29
+ std::vector< long > {sizeof (value_type )}, // strides
29
30
capsule};
30
31
}
31
32
@@ -50,14 +51,21 @@ namespace cpp2py {
50
51
51
52
template <typename T> struct py_converter <std::vector<T>> {
52
53
53
- static PyObject *c2py (std::vector<T> const &v) {
54
+ template <typename V> static PyObject *c2py (V &&v) {
55
+ static_assert (is_instantiation_of_v<std::vector, std::decay_t <V>>, " Logic error" );
56
+ using value_type = typename std::remove_reference_t <V>::value_type;
54
57
55
- if constexpr (has_npy_type<T >) {
56
- return make_numpy_proxy_from_vector (v ).to_python ();
58
+ if constexpr (has_npy_type<value_type >) {
59
+ return make_numpy_proxy_from_vector (std::forward<V>(v) ).to_python ();
57
60
} else { // Convert to Python List
58
61
PyObject *list = PyList_New (0 );
59
- for (auto const &x : v) {
60
- pyref y = py_converter<T>::c2py (x);
62
+ for (auto &x : v) {
63
+ pyref y;
64
+ if constexpr (std::is_reference_v<V>){
65
+ y = py_converter<value_type>::c2py (x);
66
+ } else { // Vector passed as rvalue
67
+ y = py_converter<value_type>::c2py (std::move (x));
68
+ }
61
69
if (y.is_null () or (PyList_Append (list, y) == -1 )) {
62
70
Py_DECREF (list);
63
71
return NULL ;
@@ -122,7 +130,7 @@ namespace cpp2py {
122
130
std::vector<T> res;
123
131
pyref seq = PySequence_Fast (ob, " expected a sequence" );
124
132
int len = PySequence_Size (ob);
125
- for (int i = 0 ; i < len; i++) res.push_back (py_converter<T >::py2c (PySequence_Fast_GET_ITEM ((PyObject *)seq, i))); // borrowed ref
133
+ for (int i = 0 ; i < len; i++) res.push_back (py_converter<std:: decay_t <T> >::py2c (PySequence_Fast_GET_ITEM ((PyObject *)seq, i))); // borrowed ref
126
134
return res;
127
135
}
128
136
};
0 commit comments