Accept any sequence type as std::tuple or std::pair

This is more Pythonic and compliments the std::vector and std::list
casters which also accept sequences.
This commit is contained in:
Dean Moldovan 2016-11-27 20:32:04 +01:00 committed by Wenzel Jakob
parent 719c1733dd
commit 107285b353
2 changed files with 15 additions and 9 deletions

View File

@ -737,12 +737,12 @@ template <typename T1, typename T2> class type_caster<std::pair<T1, T2>> {
typedef std::pair<T1, T2> type;
public:
bool load(handle src, bool convert) {
if (!src)
if (!isinstance<sequence>(src))
return false;
else if (!PyTuple_Check(src.ptr()) || PyTuple_Size(src.ptr()) != 2)
const auto seq = reinterpret_borrow<sequence>(src);
if (seq.size() != 2)
return false;
return first.load(PyTuple_GET_ITEM(src.ptr(), 0), convert) &&
second.load(PyTuple_GET_ITEM(src.ptr(), 1), convert);
return first.load(seq[0], convert) && second.load(seq[1], convert);
}
static handle cast(const type &src, return_value_policy policy, handle parent) {
@ -779,9 +779,12 @@ template <typename... Tuple> class type_caster<std::tuple<Tuple...>> {
public:
bool load(handle src, bool convert) {
if (!src || !PyTuple_Check(src.ptr()) || PyTuple_GET_SIZE(src.ptr()) != size)
if (!isinstance<sequence>(src))
return false;
return load_impl(src, convert, indices{});
const auto seq = reinterpret_borrow<sequence>(src);
if (seq.size() != size)
return false;
return load_impl(seq, convert, indices{});
}
static handle cast(const type &src, return_value_policy policy, handle parent) {
@ -800,11 +803,11 @@ protected:
template <size_t... Is>
type implicit_cast(index_sequence<Is...>) { return type(cast_op<Tuple>(std::get<Is>(value))...); }
static constexpr bool load_impl(handle, bool, index_sequence<>) { return true; }
static constexpr bool load_impl(const sequence &, bool, index_sequence<>) { return true; }
template <size_t... Is>
bool load_impl(handle src, bool convert, index_sequence<Is...>) {
for (bool r : {std::get<Is>(value).load(PyTuple_GET_ITEM(src.ptr(), Is), convert)...})
bool load_impl(const sequence &seq, bool convert, index_sequence<Is...>) {
for (bool r : {std::get<Is>(value).load(seq[Is], convert)...})
if (!r)
return false;
return true;

View File

@ -93,6 +93,9 @@ def test_instance(capture):
assert instance.pair_passthrough((True, "test")) == ("test", True)
assert instance.tuple_passthrough((True, "test", 5)) == (5, "test", True)
# Any sequence can be cast to a std::pair or std::tuple
assert instance.pair_passthrough([True, "test"]) == ("test", True)
assert instance.tuple_passthrough([True, "test", 5]) == (5, "test", True)
assert instance.get_bytes_from_string().decode() == "foo"
assert instance.get_bytes_from_str().decode() == "bar"