@@ -402,6 +402,13 @@ template <typename type> class type_caster_base : public type_caster_generic {
402
402
make_copy_constructor (src), make_move_constructor (src));
403
403
}
404
404
405
+ static handle cast_holder (const itype *src, const void *holder) {
406
+ return type_caster_generic::cast (
407
+ src, return_value_policy::take_ownership, {},
408
+ src ? &typeid (*src) : nullptr , &typeid (type),
409
+ nullptr , nullptr , holder);
410
+ }
411
+
405
412
template <typename T> using cast_op_type = pybind11::detail::cast_op_type<T>;
406
413
407
414
operator itype*() { return (type *) value; }
@@ -636,17 +643,6 @@ template <> class type_caster<std::string> {
636
643
bool success = false ;
637
644
};
638
645
639
- template <typename type, typename deleter> class type_caster <std::unique_ptr<type, deleter>> {
640
- public:
641
- static handle cast (std::unique_ptr<type, deleter> &&src, return_value_policy policy, handle parent) {
642
- handle result = type_caster_base<type>::cast (src.get (), policy, parent);
643
- if (result)
644
- src.release ();
645
- return result;
646
- }
647
- static PYBIND11_DESCR name () { return type_caster_base<type>::name (); }
648
- };
649
-
650
646
template <> class type_caster <std::wstring> {
651
647
public:
652
648
bool load (handle src, bool ) {
@@ -837,8 +833,16 @@ template <typename... Tuple> class type_caster<std::tuple<Tuple...>> {
837
833
std::tuple<make_caster<Tuple>...> value;
838
834
};
839
835
836
+ // / Helper class which abstracts away certain actions. Users can provide specializations for
837
+ // / custom holders, but it's only necessary if the type has a non-standard interface.
838
+ template <typename T>
839
+ struct holder_helper {
840
+ static auto get (const T &p) -> decltype(p.get()) { return p.get (); }
841
+ };
842
+
840
843
// / Type caster for holder types like std::shared_ptr, etc.
841
- template <typename type, typename holder_type> class type_caster_holder : public type_caster_base <type> {
844
+ template <typename type, typename holder_type>
845
+ struct copyable_holder_caster : public type_caster_base <type> {
842
846
public:
843
847
using base = type_caster_base<type>;
844
848
using base::base;
@@ -917,7 +921,7 @@ template <typename type, typename holder_type> class type_caster_holder : public
917
921
template <typename T = holder_type, detail::enable_if_t <std::is_constructible<T, const T &, type*>::value, int > = 0 >
918
922
bool try_implicit_casts (handle src, bool convert) {
919
923
for (auto &cast : typeinfo->implicit_casts ) {
920
- type_caster_holder sub_caster (*cast.first );
924
+ copyable_holder_caster sub_caster (*cast.first );
921
925
if (sub_caster.load (src, convert)) {
922
926
value = cast.second (sub_caster.value );
923
927
holder = holder_type (sub_caster.holder , (type *) value);
@@ -940,10 +944,8 @@ template <typename type, typename holder_type> class type_caster_holder : public
940
944
#endif
941
945
942
946
static handle cast (const holder_type &src, return_value_policy, handle) {
943
- return type_caster_generic::cast (
944
- src.get (), return_value_policy::take_ownership, handle (),
945
- src.get () ? &typeid (*src.get ()) : nullptr , &typeid (type),
946
- nullptr , nullptr , &src);
947
+ const auto *ptr = holder_helper<holder_type>::get (src);
948
+ return type_caster_base<type>::cast_holder (ptr, &src);
947
949
}
948
950
949
951
protected:
@@ -952,7 +954,25 @@ template <typename type, typename holder_type> class type_caster_holder : public
952
954
953
955
// / Specialize for the common std::shared_ptr, so users don't need to
954
956
template <typename T>
955
- class type_caster <std::shared_ptr<T>> : public type_caster_holder<T, std::shared_ptr<T>> { };
957
+ class type_caster <std::shared_ptr<T>> : public copyable_holder_caster<T, std::shared_ptr<T>> { };
958
+
959
+ template <typename type, typename holder_type>
960
+ struct move_only_holder_caster {
961
+ static handle cast (holder_type &&src, return_value_policy, handle) {
962
+ auto *ptr = holder_helper<holder_type>::get (src);
963
+ return type_caster_base<type>::cast_holder (ptr, &src);
964
+ }
965
+ static PYBIND11_DESCR name () { return type_caster_base<type>::name (); }
966
+ };
967
+
968
+ template <typename type, typename deleter>
969
+ class type_caster <std::unique_ptr<type, deleter>>
970
+ : public move_only_holder_caster<type, std::unique_ptr<type, deleter>> { };
971
+
972
+ template <typename type, typename holder_type>
973
+ using type_caster_holder = conditional_t <std::is_copy_constructible<holder_type>::value,
974
+ copyable_holder_caster<type, holder_type>,
975
+ move_only_holder_caster<type, holder_type>>;
956
976
957
977
template <typename T, bool Value = false > struct always_construct_holder { static constexpr bool value = Value; };
958
978
0 commit comments