Skip to content

Commit 16bb183

Browse files
committed
new move_only_holder_caster
1 parent 1562920 commit 16bb183

File tree

1 file changed

+77
-6
lines changed

1 file changed

+77
-6
lines changed

include/pybind11/cast.h

Lines changed: 77 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1515,15 +1515,86 @@ template <typename T>
15151515
class type_caster<std::shared_ptr<T>> : public copyable_holder_caster<T, std::shared_ptr<T>> { };
15161516

15171517
template <typename type, typename holder_type>
1518-
struct move_only_holder_caster {
1519-
static_assert(std::is_base_of<type_caster_base<type>, type_caster<type>>::value,
1518+
struct move_only_holder_caster : public type_caster_base<type> {
1519+
public:
1520+
using base = type_caster_base<type>;
1521+
static_assert(std::is_base_of<base, type_caster<type>>::value,
15201522
"Holder classes are only supported for custom types");
1523+
using base::base;
1524+
using base::cast;
1525+
using base::typeinfo;
1526+
using base::value;
1527+
1528+
bool load(handle& src, bool convert) {
1529+
bool success = base::template load_impl<move_only_holder_caster<type, holder_type>>(src, convert);
1530+
if (success) // if loading was successful, the instance needs to be withdrawn from src
1531+
// However, setting the src pointer to None is not sufficient.
1532+
src.ptr() = none().release().ptr();
1533+
return success;
1534+
}
1535+
1536+
template <typename T> using cast_op_type = detail::movable_cast_op_type<T>;
1537+
1538+
explicit operator type*() { return this->value; }
1539+
explicit operator type&() { return *(this->value); }
1540+
explicit operator holder_type*() { return std::addressof(holder); }
1541+
1542+
// Workaround for Intel compiler bug
1543+
// see pybind11 issue 94
1544+
#if defined(__ICC) || defined(__INTEL_COMPILER)
1545+
operator holder_type&() { return holder; }
1546+
#else
1547+
explicit operator holder_type&() { return holder; }
1548+
#endif
1549+
explicit operator holder_type&&() { value = nullptr; return std::move(holder); }
1550+
1551+
static handle cast(const holder_type &src, return_value_policy, handle) {
1552+
const auto *ptr = holder_helper<holder_type>::get(src);
1553+
return type_caster_base<type>::cast_holder(ptr, &src);
1554+
}
1555+
1556+
protected:
1557+
friend class type_caster_generic;
1558+
void check_holder_compat() {
1559+
// if (typeinfo->default_holder)
1560+
// throw cast_error("Unable to load a custom holder type from a default-holder instance");
1561+
}
15211562

1522-
static handle cast(holder_type &&src, return_value_policy, handle) {
1523-
auto *ptr = holder_helper<holder_type>::get(src);
1524-
return type_caster_base<type>::cast_holder(ptr, std::addressof(src));
1563+
bool load_value(value_and_holder &&v_h) {
1564+
if (v_h.holder_constructed()) {
1565+
value = v_h.value_ptr();
1566+
holder = std::move(v_h.template holder<holder_type>());
1567+
return true;
1568+
} else {
1569+
throw cast_error("Unable to cast from non-held to held instance (T& to Holder<T>) "
1570+
#if defined(NDEBUG)
1571+
"(compile in debug mode for type information)");
1572+
#else
1573+
"of type '" + type_id<holder_type>() + "''");
1574+
#endif
1575+
}
1576+
}
1577+
1578+
template <typename T = holder_type, detail::enable_if_t<!std::is_constructible<T, const T &, type*>::value, int> = 0>
1579+
bool try_implicit_casts(handle, bool) { return false; }
1580+
1581+
template <typename T = holder_type, detail::enable_if_t<std::is_constructible<T, const T &, type*>::value, int> = 0>
1582+
bool try_implicit_casts(handle src, bool convert) {
1583+
for (auto &cast : typeinfo->implicit_casts) {
1584+
move_only_holder_caster sub_caster(*cast.first);
1585+
if (sub_caster.load(src, convert)) {
1586+
value = cast.second(sub_caster.value);
1587+
holder = holder_type(sub_caster.holder, (type *) value);
1588+
return true;
1589+
}
1590+
}
1591+
return false;
15251592
}
1526-
static constexpr auto name = type_caster_base<type>::name;
1593+
1594+
static bool try_direct_conversions(handle) { return false; }
1595+
1596+
1597+
holder_type holder;
15271598
};
15281599

15291600
template <typename type, typename deleter>

0 commit comments

Comments
 (0)