Skip to content

Commit a271c27

Browse files
committed
Simplifications in tuple and vector converter, Improve error messages
1 parent 3e4667a commit a271c27

File tree

2 files changed

+25
-26
lines changed

2 files changed

+25
-26
lines changed

c++/cpp2py/converters/tuple.hpp

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -15,45 +15,48 @@ namespace cpp2py {
1515
// c2py implementation
1616
template <typename T, auto... Is> static PyObject *c2py_impl(T &&t, std::index_sequence<Is...>) {
1717
auto objs = std::array<pyref, sizeof...(Is)>{convert_to_python(std::get<Is>(std::forward<T>(t)))...};
18-
bool one_is_null = std::accumulate(std::begin(objs), std::end(objs), false, [](bool x, PyObject *a) { return x or (a == NULL); });
18+
bool one_is_null = std::any_of(std::begin(objs), std::end(objs), [](PyObject *a) { return a == NULL; });
1919
if (one_is_null) return NULL;
2020
return PyTuple_Pack(sizeof...(Types), (PyObject *)(objs[Is])...);
2121
}
2222

23-
// is_convertible implementation
24-
template <auto... Is> static bool is_convertible_impl(PyObject *seq, bool raise_exception, std::index_sequence<Is...>) {
25-
return (py_converter<std::decay_t<Types>>::is_convertible(PySequence_Fast_GET_ITEM(seq, Is), raise_exception) and ...);
26-
}
27-
28-
template <auto... Is> static auto py2c_impl(PyObject *seq, std::index_sequence<Is...>) {
29-
return std::make_tuple(py_converter<std::decay_t<Types>>::py2c(PySequence_Fast_GET_ITEM(seq, Is))...);
30-
}
31-
3223
public:
33-
// -----------------------------------------
34-
3524
template <typename T> static PyObject *c2py(T &&t) {
3625
static_assert(is_instantiation_of_v<std::tuple, std::decay_t<T>>, "Logic Error");
3726
return c2py_impl(std::forward<T>(t), std::make_index_sequence<sizeof...(Types)>());
3827
}
3928

4029
// -----------------------------------------
4130

31+
private:
32+
// is_convertible implementation
33+
template <auto... Is> static bool is_convertible_impl(PyObject *seq, bool raise_exception, std::index_sequence<Is...>) {
34+
return (py_converter<std::decay_t<Types>>::is_convertible(PySequence_Fast_GET_ITEM(seq, Is), raise_exception) and ...);
35+
}
36+
37+
public:
4238
static bool is_convertible(PyObject *ob, bool raise_exception) {
43-
if (PySequence_Check(ob)) {
44-
pyref seq = PySequence_Fast(ob, "expected a sequence");
45-
// Sizes must match! Could we relax this condition to '<'?
46-
if (PySequence_Fast_GET_SIZE((PyObject *)seq) != std::tuple_size<tuple_t>::value) goto _false;
47-
if (!is_convertible_impl((PyObject *)seq, raise_exception, std::make_index_sequence<sizeof...(Types)>())) goto _false;
48-
return true;
39+
if (not PySequence_Check(ob)) {
40+
if (raise_exception) { PyErr_SetString(PyExc_TypeError, "Cannot convert non-sequence to std::tuple"); }
41+
return false;
42+
}
43+
pyref seq = PySequence_Fast(ob, "expected a sequence");
44+
// Sizes must match! Could we relax this condition to '<'?
45+
if (PySequence_Fast_GET_SIZE((PyObject *)seq) != std::tuple_size<tuple_t>::value) {
46+
if (raise_exception) { PyErr_SetString(PyExc_TypeError, "Cannot convert to std::tuple due to improper length"); }
47+
return false;
4948
}
50-
_false:
51-
if (raise_exception) { PyErr_SetString(PyExc_TypeError, "Cannot convert to std::tuple"); }
52-
return false;
49+
return is_convertible_impl((PyObject *)seq, raise_exception, std::make_index_sequence<sizeof...(Types)>());
5350
}
5451

5552
// -----------------------------------------
5653

54+
private:
55+
template <auto... Is> static auto py2c_impl(PyObject *seq, std::index_sequence<Is...>) {
56+
return std::make_tuple(py_converter<std::decay_t<Types>>::py2c(PySequence_Fast_GET_ITEM(seq, Is))...);
57+
}
58+
59+
public:
5760
static tuple_t py2c(PyObject *ob) {
5861
pyref seq = PySequence_Fast(ob, "expected a sequence");
5962
return py2c_impl((PyObject *)seq, std::make_index_sequence<sizeof...(Types)>());

c++/cpp2py/converters/vector.hpp

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -99,11 +99,7 @@ namespace cpp2py {
9999
pyref seq = PySequence_Fast(ob, "expected a sequence");
100100
int len = PySequence_Size(ob);
101101
for (int i = 0; i < len; i++) {
102-
if (!py_converter<T>::is_convertible(PySequence_Fast_GET_ITEM((PyObject *)seq, i), false)) { // borrowed ref
103-
if (raise_exception) {
104-
auto err = std::string{"Cannot convert sequence to std::vector due to element at position "} + std::to_string(i);
105-
PyErr_SetString(PyExc_TypeError, err.c_str());
106-
}
102+
if (!py_converter<T>::is_convertible(PySequence_Fast_GET_ITEM((PyObject *)seq, i), raise_exception)) { // borrowed ref
107103
return false;
108104
}
109105
}

0 commit comments

Comments
 (0)