@@ -908,6 +908,14 @@ struct handle_type_name<kwargs> {
908908
909909template <typename type>
910910struct pyobject_caster {
911+ template <typename T = type, enable_if_t <std::is_same<T, handle>::value, int > = 0 >
912+ pyobject_caster () : value() {}
913+
914+ // `type` may not be default constructible (e.g. frozenset, anyset). Initializing `value`
915+ // to a nil handle is safe since it will only be accessed if `load` succeeds.
916+ template <typename T = type, enable_if_t <std::is_base_of<object, T>::value, int > = 0 >
917+ pyobject_caster () : value(reinterpret_steal<type>(handle())) {}
918+
911919 template <typename T = type, enable_if_t <std::is_same<T, handle>::value, int > = 0 >
912920 bool load (handle src, bool /* convert */ ) {
913921 value = src;
@@ -1001,6 +1009,8 @@ struct return_value_policy_override<
10011009// Basic python -> C++ casting; throws if casting fails
10021010template <typename T, typename SFINAE>
10031011type_caster<T, SFINAE> &load_type (type_caster<T, SFINAE> &conv, const handle &handle) {
1012+ static_assert (!detail::is_pyobject<T>::value,
1013+ " Internal error: type_caster should only be used for C++ types" );
10041014 if (!conv.load (handle, true )) {
10051015#if !defined(PYBIND11_DETAILED_ERROR_MESSAGES)
10061016 throw cast_error (" Unable to cast Python instance to C++ type (#define "
@@ -1091,21 +1101,30 @@ detail::enable_if_t<!detail::move_never<T>::value, T> move(object &&obj) {
10911101// - If both movable and copyable, check ref count: if 1, move; otherwise copy
10921102// - Otherwise (not movable), copy.
10931103template <typename T>
1094- detail::enable_if_t <detail::move_always<T>::value, T> cast (object &&object) {
1104+ detail::enable_if_t <!detail::is_pyobject<T>::value && detail::move_always<T>::value, T>
1105+ cast (object &&object) {
10951106 return move<T>(std::move (object));
10961107}
10971108template <typename T>
1098- detail::enable_if_t <detail::move_if_unreferenced<T>::value, T> cast (object &&object) {
1109+ detail::enable_if_t <!detail::is_pyobject<T>::value && detail::move_if_unreferenced<T>::value, T>
1110+ cast (object &&object) {
10991111 if (object.ref_count () > 1 ) {
11001112 return cast<T>(object);
11011113 }
11021114 return move<T>(std::move (object));
11031115}
11041116template <typename T>
1105- detail::enable_if_t <detail::move_never<T>::value, T> cast (object &&object) {
1117+ detail::enable_if_t <!detail::is_pyobject<T>::value && detail::move_never<T>::value, T>
1118+ cast (object &&object) {
11061119 return cast<T>(object);
11071120}
11081121
1122+ // pytype rvalue -> pytype (calls converting constructor)
1123+ template <typename T>
1124+ detail::enable_if_t <detail::is_pyobject<T>::value, T> cast (object &&object) {
1125+ return T (std::move (object));
1126+ }
1127+
11091128template <typename T>
11101129T object::cast () const & {
11111130 return pybind11::cast<T>(*this );
0 commit comments