Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix casters of STL containers with char* #2303

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion include/pybind11/cast.h
Original file line number Diff line number Diff line change
Expand Up @@ -1347,7 +1347,7 @@ template <typename CharT> struct type_caster<CharT, enable_if_t<is_std_char_type
return StringCaster::cast(StringType(1, src), policy, parent);
}

operator CharT*() { return none ? nullptr : const_cast<CharT *>(static_cast<StringType &>(str_caster).c_str()); }
operator CharT*() { return none ? nullptr : &static_cast<StringType &>(str_caster)[0]; }
operator CharT&() {
if (none)
throw value_error("Cannot convert None to a character");
Expand Down
43 changes: 37 additions & 6 deletions include/pybind11/stl.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,11 @@ template <typename Type, typename Key> struct set_caster {
return false;
auto s = reinterpret_borrow<pybind11::set>(src);
value.clear();
subcasters.clear();
subcasters.reserve(s.size());
for (auto entry : s) {
key_conv conv;
subcasters.emplace_back();
auto &conv = subcasters.back();
if (!conv.load(entry, convert))
return false;
value.insert(cast_op<Key &&>(std::move(conv)));
Expand All @@ -96,6 +99,9 @@ template <typename Type, typename Key> struct set_caster {
}

PYBIND11_TYPE_CASTER(type, _("Set[") + key_conv::name + _("]"));

private:
std::vector<key_conv> subcasters;
};

template <typename Type, typename Key, typename Value> struct map_caster {
Expand All @@ -107,9 +113,13 @@ template <typename Type, typename Key, typename Value> struct map_caster {
return false;
auto d = reinterpret_borrow<dict>(src);
value.clear();
subcasters.clear();
subcasters.reserve(d.size());
for (auto it : d) {
key_conv kconv;
value_conv vconv;
subcasters.emplace_back();
auto &conv_pair = subcasters.back();
auto &kconv = conv_pair.first;
auto &vconv = conv_pair.second;
if (!kconv.load(it.first.ptr(), convert) ||
!vconv.load(it.second.ptr(), convert))
return false;
Expand Down Expand Up @@ -138,6 +148,9 @@ template <typename Type, typename Key, typename Value> struct map_caster {
}

PYBIND11_TYPE_CASTER(Type, _("Dict[") + key_conv::name + _(", ") + value_conv::name + _("]"));

private:
std::vector<std::pair<key_conv, value_conv>> subcasters;
};

template <typename Type, typename Value> struct list_caster {
Expand All @@ -149,8 +162,11 @@ template <typename Type, typename Value> struct list_caster {
auto s = reinterpret_borrow<sequence>(src);
value.clear();
reserve_maybe(s, &value);
subcasters.clear();
subcasters.reserve(s.size());
for (auto it : s) {
value_conv conv;
subcasters.emplace_back();
auto &conv = subcasters.back();
if (!conv.load(it, convert))
return false;
value.push_back(cast_op<Value &&>(std::move(conv)));
Expand Down Expand Up @@ -181,6 +197,9 @@ template <typename Type, typename Value> struct list_caster {
}

PYBIND11_TYPE_CASTER(Type, _("List[") + value_conv::name + _("]"));

private:
std::vector<value_conv> subcasters;
};

template <typename Type, typename Alloc> struct type_caster<std::vector<Type, Alloc>>
Expand Down Expand Up @@ -214,9 +233,12 @@ template <typename ArrayType, typename Value, bool Resizable, size_t Size = 0> s
auto l = reinterpret_borrow<sequence>(src);
if (!require_size(l.size()))
return false;
subcasters.clear();
subcasters.reserve(l.size());
size_t ctr = 0;
for (auto it : l) {
value_conv conv;
subcasters.emplace_back();
auto &conv = subcasters.back();
if (!conv.load(it, convert))
return false;
value[ctr++] = cast_op<Value &&>(std::move(conv));
Expand All @@ -238,6 +260,9 @@ template <typename ArrayType, typename Value, bool Resizable, size_t Size = 0> s
}

PYBIND11_TYPE_CASTER(ArrayType, _("List[") + value_conv::name + _<Resizable>(_(""), _("[") + _<Size>() + _("]")) + _("]"));

private:
std::vector<value_conv> subcasters;
};

template <typename Type, size_t Size> struct type_caster<std::array<Type, Size>>
Expand Down Expand Up @@ -278,7 +303,6 @@ template<typename T> struct optional_caster {
} else if (src.is_none()) {
return true; // default-constructed value is already empty
}
value_conv inner_caster;
if (!inner_caster.load(src, convert))
return false;

Expand All @@ -287,6 +311,9 @@ template<typename T> struct optional_caster {
}

PYBIND11_TYPE_CASTER(T, _("Optional[") + value_conv::name + _("]"));

private:
value_conv inner_caster;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call it subcaster, for consistency's sake.

};

#if PYBIND11_HAS_OPTIONAL
Expand Down Expand Up @@ -342,6 +369,7 @@ struct variant_caster<V<Ts...>> {
auto caster = make_caster<U>();
if (caster.load(src, convert)) {
value = cast_op<U>(caster);
subcaster = std::move(caster);
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, are casters movable?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They are.

return true;
}
return load_alternative(src, convert, type_list<Us...>{});
Expand All @@ -367,6 +395,9 @@ struct variant_caster<V<Ts...>> {

using Type = V<Ts...>;
PYBIND11_TYPE_CASTER(Type, _("Union[") + detail::concat(make_caster<Ts>::name...) + _("]"));

private:
V<make_caster<Ts>...> subcaster;
};

#if PYBIND11_HAS_VARIANT
Expand Down