Skip to content

Commit 01cd04c

Browse files
committed
For c2py of stl types take argument by value and move elements
1 parent 660051b commit 01cd04c

File tree

8 files changed

+33
-32
lines changed

8 files changed

+33
-32
lines changed

c++/cpp2py/converters/map.hpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@ namespace cpp2py {
55

66
template <typename K, typename V> struct py_converter<std::map<K, V>> {
77

8-
static PyObject *c2py(std::map<K, V> const &m) {
8+
static PyObject *c2py(std::map<K, V> m) {
99
PyObject *d = PyDict_New();
1010
for (auto &x : m) {
11-
pyref k = py_converter<K>::c2py(x.first);
11+
pyref k = py_converter<std::decay_t<K>>::c2py(std::move(x.first));
1212
// if the K is a list, we transform into a tuple
1313
if (PyList_Check(k)) k = PyList_AsTuple(k);
14-
pyref v = py_converter<V>::c2py(x.second);
14+
pyref v = py_converter<std::decay_t<V>>::c2py(std::move(x.second));
1515
if (k.is_null() or v.is_null() or (PyDict_SetItem(d, k, v) == -1)) {
1616
Py_DECREF(d);
1717
return NULL;

c++/cpp2py/converters/optional.hpp

+5-5
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@ namespace cpp2py {
33

44
template <typename T> struct py_converter<std::optional<T>> {
55

6-
using conv = py_converter<T>;
6+
using conv = py_converter<std::decay_t<T>>;
77

8-
static PyObject *c2py(std::optional<T> &op) {
9-
if (!bool(op)) Py_RETURN_NONE;
10-
return conv::c2py(*op);
11-
}
8+
static PyObject *c2py(std::optional<T> op) {
9+
if (!bool(op)) Py_RETURN_NONE;
10+
return conv::c2py(std::move(*op));
11+
}
1212

1313
static bool is_convertible(PyObject *ob, bool raise_exception) {
1414
return ((ob == Py_None) or conv::is_convertible(ob, raise_exception));

c++/cpp2py/converters/pair.hpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ namespace cpp2py {
55

66
template <typename T1, typename T2> struct py_converter<std::pair<T1, T2>> {
77

8-
static PyObject *c2py(std::pair<T1, T2> const &p) {
9-
pyref x1 = py_converter<T1>::c2py(std::get<0>(p));
10-
pyref x2 = py_converter<T2>::c2py(std::get<1>(p));
8+
static PyObject *c2py(std::pair<T1, T2> p) {
9+
pyref x1 = py_converter<std::decay_t<T1>>::c2py(std::move(std::get<0>(p)));
10+
pyref x2 = py_converter<std::decay_t<T2>>::c2py(std::move(std::get<1>(p)));
1111
if (x1.is_null() or x2.is_null()) return NULL;
1212
return PyTuple_Pack(2, (PyObject *)x1, (PyObject *)x2);
1313
}

c++/cpp2py/converters/set.hpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ namespace cpp2py {
55

66
template <typename K> struct py_converter<std::set<K>> {
77

8-
static PyObject *c2py(std::set<K> const &s) {
8+
static PyObject *c2py(std::set<K> s) {
99
PyObject *set = PySet_New(NULL);
1010
for (auto &x : s) {
11-
pyref y = py_converter<K>::c2py(x);
11+
pyref y = py_converter<std::decay_t<K>>::c2py(std::move(x));
1212
if (y.is_null() or (PySet_Add(set, y) == -1)) {
1313
Py_DECREF(set);
1414
return NULL;

c++/cpp2py/converters/std_array.hpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@ namespace cpp2py {
66
template <typename T, size_t R> struct py_converter<std::array<T, R>> {
77
// --------------------------------------
88

9-
static PyObject *c2py(std::array<T, R> const &v) {
9+
static PyObject *c2py(std::array<T, R> v) {
1010
PyObject *list = PyList_New(0);
11-
for (auto const &x : v) {
12-
pyref y = py_converter<T>::c2py(x);
11+
for (auto &x : v) {
12+
pyref y = py_converter<std::decay_t<T>>::c2py(std::move(x));
1313
if (y.is_null() or (PyList_Append(list, y) == -1)) {
1414
Py_DECREF(list);
1515
return NULL;

c++/cpp2py/converters/tuple.hpp

+5-5
Original file line numberDiff line numberDiff line change
@@ -11,28 +11,28 @@ namespace cpp2py {
1111
using tuple_t = std::tuple<Types...>;
1212

1313
// c2py implementation
14-
template <std::size_t... Is> static PyObject *c2py_impl(tuple_t const &t, std::index_sequence<Is...>) {
15-
auto objs = std::array<pyref, sizeof...(Is)>{pyref(py_converter<Types>::c2py(std::get<Is>(t)))...};
14+
template <std::size_t... Is> static PyObject *c2py_impl(tuple_t t, std::index_sequence<Is...>) {
15+
auto objs = std::array<pyref, sizeof...(Is)>{pyref(py_converter<std::decay_t<Types>>::c2py(std::move(std::get<Is>(t))))...};
1616
bool one_is_null = std::accumulate(std::begin(objs), std::end(objs), false, [](bool x, PyObject *a) { return x or (a == NULL); });
1717
if (one_is_null) return NULL;
1818
return PyTuple_Pack(sizeof...(Types), (PyObject *)(objs[Is])...);
1919
}
2020

2121
// is_convertible implementation
2222
template <int N, typename T, typename... Tail> static bool is_convertible_impl(PyObject *seq, bool raise_exception) {
23-
return py_converter<T>::is_convertible(PySequence_Fast_GET_ITEM(seq, N), raise_exception)
23+
return py_converter<std::decay_t<T>>::is_convertible(PySequence_Fast_GET_ITEM(seq, N), raise_exception)
2424
&& is_convertible_impl<N + 1, Tail...>(seq, raise_exception);
2525
}
2626
template <int> static bool is_convertible_impl(PyObject *seq, bool raise_exception) { return true; }
2727

2828
template <size_t... Is> static auto py2c_impl(std::index_sequence<Is...>, PyObject *seq) {
29-
return std::make_tuple(py_converter<Types>::py2c(PySequence_Fast_GET_ITEM(seq, Is))...);
29+
return std::make_tuple(py_converter<std::decay_t<Types>>::py2c(PySequence_Fast_GET_ITEM(seq, Is))...);
3030
}
3131

3232
public:
3333
// -----------------------------------------
3434

35-
static PyObject *c2py(tuple_t const &t) { return c2py_impl(t, std::make_index_sequence<sizeof...(Types)>()); }
35+
static PyObject *c2py(tuple_t t) { return c2py_impl(std::move(t), std::make_index_sequence<sizeof...(Types)>()); }
3636

3737
// -----------------------------------------
3838

c++/cpp2py/converters/variant.hpp

+4-2
Original file line numberDiff line numberDiff line change
@@ -45,18 +45,20 @@ namespace cpp2py {
4545
}
4646

4747
struct _visitor {
48-
template <typename U> PyObject *operator()(U const &x) { return py_converter<U>::c2py(x); }
48+
template <typename U> PyObject *operator()(U x) { return py_converter<std::decay_t<U>>::c2py(std::move(x)); }
4949
};
5050

5151
public:
52+
static PyObject *c2py(std::variant<T...> v) { return visit(_visitor{}, std::move(v)); }
53+
5254
static PyObject *c2py(std::variant<T...> const &v) {
5355
//auto l = [](auto const &x) -> PyObject * { return py_converter<decltype(x)>::c2py(x); };
5456
return visit(_visitor{}, v);
5557
//return visit(_visitor{}, v);
5658
}
5759

5860
static bool is_convertible(PyObject *ob, bool raise_exception) {
59-
if ((... or py_converter<T>::is_convertible(ob, false))) return true;
61+
if ((... or py_converter<std::decay_t<T>>::is_convertible(ob, false))) return true;
6062
if (raise_exception) { PyErr_SetString(PyExc_TypeError, "Cannot convert to std::variant"); }
6163
return false;
6264
}

c++/cpp2py/converters/vector.hpp

+8-9
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,19 @@
99
namespace cpp2py {
1010

1111
template <typename T> static void delete_pycapsule(PyObject *capsule) {
12-
auto *ptr = static_cast<std::unique_ptr<T[]> *>(PyCapsule_GetPointer(capsule, "guard"));
12+
auto *ptr = static_cast<std::vector<T> *>(PyCapsule_GetPointer(capsule, "guard"));
1313
delete ptr;
1414
}
1515

1616
// Convert vector to numpy_proxy, WARNING: Deep Copy
17-
template <typename T> numpy_proxy make_numpy_proxy_from_vector(std::vector<T> const &v) {
17+
template <typename T> numpy_proxy make_numpy_proxy_from_vector(std::vector<T> v) {
1818

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>);
19+
auto *vec_heap = new std::vector<T>{std::move(v)};
20+
auto capsule = PyCapsule_New(vec_heap, "guard", &delete_pycapsule<T>);
2221

2322
return {1, // rank
2423
npy_type<std::remove_const_t<T>>,
25-
(void *)data_ptr->get(),
24+
(void *)vec_heap->data(),
2625
std::is_const_v<T>,
2726
v_t{static_cast<long>(v.size())}, // extents
2827
v_t{sizeof(T)}, // strides
@@ -46,14 +45,14 @@ namespace cpp2py {
4645

4746
template <typename T> struct py_converter<std::vector<T>> {
4847

49-
static PyObject *c2py(std::vector<T> const &v) {
48+
static PyObject *c2py(std::vector<T> v) {
5049

5150
if constexpr (has_npy_type<T>) {
52-
return make_numpy_proxy_from_vector(v).to_python();
51+
return make_numpy_proxy_from_vector(std::move(v)).to_python();
5352
} else { // Convert to Python List
5453
PyObject *list = PyList_New(0);
5554
for (auto const &x : v) {
56-
pyref y = py_converter<T>::c2py(x);
55+
pyref y = py_converter<T>::c2py(std::move(x));
5756
if (y.is_null() or (PyList_Append(list, y) == -1)) {
5857
Py_DECREF(list);
5958
return NULL;

0 commit comments

Comments
 (0)