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

Factoring out make_constructor from type_caster_base (for reuse under PR #2672). #2798

Closed
wants to merge 2 commits into from
Closed
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
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 @@ -905,7 +929,8 @@ template <typename type> class type_caster_base : public type_caster_generic {
auto st = src_and_type(src);
return type_caster_generic::cast(
st.first, 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_holder(const itype *src, const void *holder) {
Expand All @@ -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