mirror of
https://github.com/pybind/pybind11.git
synced 2026-05-12 17:26:13 +00:00
Implement py::init_alias<>() constructors
This commit adds support for forcing alias type initialization by
defining constructors with `py::init_alias<arg1, arg2>()` instead of
`py::init<arg1, arg2>()`. Currently py::init<> only results in Alias
initialization if the type is extended in python, or the given
arguments can't be used to construct the base type, but can be used to
construct the alias. py::init_alias<>, in contrast, always invokes the
constructor of the alias type.
It looks like this was already the intention of
`py::detail::init_alias`, which was forward-declared in
86d825f330, but was apparently never
finished: despite the existance of a .def method accepting it, the
`detail::init_alias` class isn't actually defined anywhere.
This commit completes the feature (or possibly repurposes it), allowing
declaration of classes that will always initialize the trampoline which
is (as I argued in #397) sometimes useful.
This commit is contained in:
@@ -1107,17 +1107,17 @@ private:
|
||||
|
||||
NAMESPACE_BEGIN(detail)
|
||||
template <typename... Args> struct init {
|
||||
template <typename Class, typename... Extra, typename std::enable_if<!Class::has_alias, int>::type = 0>
|
||||
void execute(Class &cl, const Extra&... extra) const {
|
||||
template <typename Class, typename... Extra, enable_if_t<!Class::has_alias, int> = 0>
|
||||
static void execute(Class &cl, const Extra&... extra) {
|
||||
using Base = typename Class::type;
|
||||
/// Function which calls a specific C++ in-place constructor
|
||||
cl.def("__init__", [](Base *self_, Args... args) { new (self_) Base(args...); }, extra...);
|
||||
}
|
||||
|
||||
template <typename Class, typename... Extra,
|
||||
typename std::enable_if<Class::has_alias &&
|
||||
std::is_constructible<typename Class::type, Args...>::value, int>::type = 0>
|
||||
void execute(Class &cl, const Extra&... extra) const {
|
||||
enable_if_t<Class::has_alias &&
|
||||
std::is_constructible<typename Class::type, Args...>::value, int> = 0>
|
||||
static void execute(Class &cl, const Extra&... extra) {
|
||||
using Base = typename Class::type;
|
||||
using Alias = typename Class::type_alias;
|
||||
handle cl_type = cl;
|
||||
@@ -1130,14 +1130,22 @@ template <typename... Args> struct init {
|
||||
}
|
||||
|
||||
template <typename Class, typename... Extra,
|
||||
typename std::enable_if<Class::has_alias &&
|
||||
!std::is_constructible<typename Class::type, Args...>::value, int>::type = 0>
|
||||
void execute(Class &cl, const Extra&... extra) const {
|
||||
enable_if_t<Class::has_alias &&
|
||||
!std::is_constructible<typename Class::type, Args...>::value, int> = 0>
|
||||
static void execute(Class &cl, const Extra&... extra) {
|
||||
init_alias<Args...>::execute(cl, extra...);
|
||||
}
|
||||
};
|
||||
template <typename... Args> struct init_alias {
|
||||
template <typename Class, typename... Extra,
|
||||
enable_if_t<Class::has_alias && std::is_constructible<typename Class::type_alias, Args...>::value, int> = 0>
|
||||
static void execute(Class &cl, const Extra&... extra) {
|
||||
using Alias = typename Class::type_alias;
|
||||
cl.def("__init__", [](Alias *self_, Args... args) { new (self_) Alias(args...); }, extra...);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
inline void keep_alive_impl(handle nurse, handle patient) {
|
||||
/* Clever approach based on weak references taken from Boost.Python */
|
||||
if (!nurse || !patient)
|
||||
@@ -1172,6 +1180,7 @@ struct iterator_state {
|
||||
NAMESPACE_END(detail)
|
||||
|
||||
template <typename... Args> detail::init<Args...> init() { return detail::init<Args...>(); }
|
||||
template <typename... Args> detail::init_alias<Args...> init_alias() { return detail::init_alias<Args...>(); }
|
||||
|
||||
template <typename Iterator,
|
||||
typename Sentinel,
|
||||
|
||||
Reference in New Issue
Block a user