Skip to content

Commit

Permalink
Using factored-out make_constructor (PR pybind#2798), removing duplic…
Browse files Browse the repository at this point in the history
…ate code.
  • Loading branch information
Ralf W. Grosse-Kunstleve committed Jan 25, 2021
1 parent e243b0e commit c364f78
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 52 deletions.
49 changes: 26 additions & 23 deletions include/pybind11/cast.h
Original file line number Diff line number Diff line change
Expand Up @@ -816,6 +816,30 @@ template <typename Container> struct is_copy_assignable<Container, enable_if_t<a
template <typename T1, typename T2> struct is_copy_assignable<std::pair<T1, T2>>
: all_of<is_copy_assignable<T1>, is_copy_assignable<T2>> {};

// Helper for type_caster_base.
struct make_constructor {
using Constructor = void *(*)(const void *);

/* Only enabled when the types are {copy,move}-constructible *and* when the type
does not have a private operator new implementation. */
template <typename T, typename = enable_if_t<is_copy_constructible<T>::value>>
static auto make_copy_constructor(const T *x) -> decltype(new T(*x), Constructor{}) {
return [](const void *arg) -> void * {
return new T(*reinterpret_cast<const T *>(arg));
};
}

template <typename T, typename = enable_if_t<std::is_move_constructible<T>::value>>
static auto make_move_constructor(const T *x) -> decltype(new T(std::move(*const_cast<T *>(x))), Constructor{}) {
return [](const void *arg) -> void * {
return new T(std::move(*const_cast<T *>(reinterpret_cast<const T *>(arg))));
};
}

static Constructor make_copy_constructor(...) { return nullptr; }
static Constructor make_move_constructor(...) { return nullptr; }
};

PYBIND11_NAMESPACE_END(detail)

// polymorphic_type_hook<itype>::get(src, tinfo) determines whether the object pointed
Expand Down Expand Up @@ -858,7 +882,8 @@ struct polymorphic_type_hook : public polymorphic_type_hook_base<itype> {};
PYBIND11_NAMESPACE_BEGIN(detail)

/// Generic type caster for objects stored on the heap
template <typename type> class type_caster_base : public type_caster_generic {
template <typename type> class type_caster_base : public type_caster_generic,
protected make_constructor {
using itype = intrinsic_t<type>;

public:
Expand Down Expand Up @@ -919,28 +944,6 @@ template <typename type> class type_caster_base : public type_caster_generic {

operator itype*() { return (type *) value; }
operator itype&() { if (!value) throw reference_cast_error(); return *((itype *) value); }

protected:
using Constructor = void *(*)(const void *);

/* Only enabled when the types are {copy,move}-constructible *and* when the type
does not have a private operator new implementation. */
template <typename T, typename = enable_if_t<is_copy_constructible<T>::value>>
static auto make_copy_constructor(const T *x) -> decltype(new T(*x), Constructor{}) {
return [](const void *arg) -> void * {
return new T(*reinterpret_cast<const T *>(arg));
};
}

template <typename T, typename = enable_if_t<std::is_move_constructible<T>::value>>
static auto make_move_constructor(const T *x) -> decltype(new T(std::move(*const_cast<T *>(x))), Constructor{}) {
return [](const void *arg) -> void * {
return new T(std::move(*const_cast<T *>(reinterpret_cast<const T *>(arg))));
};
}

static Constructor make_copy_constructor(...) { return nullptr; }
static Constructor make_move_constructor(...) { return nullptr; }
};

template <typename type, typename SFINAE = void> class type_caster : public type_caster_base<type> { };
Expand Down
31 changes: 2 additions & 29 deletions tests/test_classh_wip.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,8 @@ struct type_caster<mpty> : smart_holder_type_caster_load<mpty> {
policy,
parent,
st.second,
make_copy_constructor(src),
make_move_constructor(src));
make_constructor::make_copy_constructor(src),
make_constructor::make_move_constructor(src));
}

static handle cast(mpty *src, return_value_policy policy, handle parent) {
Expand Down Expand Up @@ -156,33 +156,6 @@ struct type_caster<mpty> : smart_holder_type_caster_load<mpty> {

// clang-format on

// type_caster_base BEGIN
// clang-format off

using Constructor = void *(*)(const void *);

/* Only enabled when the types are {copy,move}-constructible *and* when the type
does not have a private operator new implementation. */
template <typename T, typename = enable_if_t<is_copy_constructible<T>::value>>
static auto make_copy_constructor(const T *x) -> decltype(new T(*x), Constructor{}) {
return [](const void *arg) -> void * {
return new T(*reinterpret_cast<const T *>(arg));
};
}

template <typename T, typename = enable_if_t<std::is_move_constructible<T>::value>>
static auto make_move_constructor(const T *x) -> decltype(new T(std::move(*const_cast<T *>(x))), Constructor{}) {
return [](const void *arg) -> void * {
return new T(std::move(*const_cast<T *>(reinterpret_cast<const T *>(arg))));
};
}

static Constructor make_copy_constructor(...) { return nullptr; }
static Constructor make_move_constructor(...) { return nullptr; }

// clang-format on
// type_caster_base END

// Originally type_caster_generic::cast.
PYBIND11_NOINLINE static handle cast_const_raw_ptr(const void *_src,
return_value_policy policy,
Expand Down

0 comments on commit c364f78

Please sign in to comment.