@@ -45,6 +45,8 @@ template <typename Class> using Cpp = typename Class::type;
45
45
template <typename Class> using Alias = typename Class::type_alias;
46
46
template <typename Class> using Holder = typename Class::holder_type;
47
47
48
+ template <typename Class> using is_alias_constructible = std::is_constructible<Alias<Class>, Cpp<Class> &&>;
49
+
48
50
// Takes a Cpp pointer and returns true if it actually is a polymorphic Alias instance.
49
51
template <typename Class, enable_if_t <Class::has_alias, int > = 0 >
50
52
bool is_alias (Cpp<Class> *ptr) {
@@ -59,15 +61,17 @@ constexpr bool is_alias(void *) { return false; }
59
61
// constructed from an rvalue reference of the base Cpp type. This means that Alias classes
60
62
// can, when appropriate, simply define a `Alias(Cpp &&)` constructor rather than needing to
61
63
// inherit all the base class constructors.
62
- template <typename Class, enable_if_t <std::is_constructible<Alias<Class>, Cpp<Class> &&>::value, int > = 0 >
63
- bool construct_alias_from_cpp (value_and_holder &v_h, Cpp<Class> &&base) {
64
+ template <typename Class>
65
+ void construct_alias_from_cpp (std::true_type /* is_alias_constructible*/ ,
66
+ value_and_holder &v_h, Cpp<Class> &&base) {
64
67
deallocate (v_h) = new Alias<Class>(std::move (base));
65
- return true ;
66
68
}
67
- // Fallback of the above for aliases without an `Alias(Cpp &&) constructor; does nothing and
68
- // returns false to signal the non-availability of the special constructor.
69
- template <typename Class, enable_if_t <!std::is_constructible<Alias<Class>, Cpp<Class> &&>::value, int > = 0 >
70
- constexpr bool construct_alias_from_cpp (value_and_holder &, Cpp<Class> &&) { return false ; }
69
+ template <typename Class>
70
+ [[noreturn]] void construct_alias_from_cpp (std::false_type /* !is_alias_constructible*/ ,
71
+ value_and_holder &, Cpp<Class> &&) {
72
+ throw type_error (" pybind11::init(): unable to convert returned instance to required "
73
+ " alias class: no `Alias<Class>(Class &&)` constructor available" );
74
+ }
71
75
72
76
// Error-generating fallback for factories that don't match one of the below construction
73
77
// mechanisms.
@@ -101,15 +105,13 @@ void construct(value_and_holder &v_h, Cpp<Class> *ptr, bool need_alias) {
101
105
v_h.type ->dealloc (v_h); // Destroys the moved-out holder remains, resets value ptr to null
102
106
v_h.set_instance_registered (false );
103
107
104
- if (construct_alias_from_cpp<Class>(v_h, std::move (*ptr)))
105
- return ;
106
- else
107
- throw type_error (" pybind11::init(): pointer could not be cast or "
108
- " converted to an alias instance" );
108
+ construct_alias_from_cpp<Class>(is_alias_constructible<Class>{}, v_h, std::move (*ptr));
109
+ }
110
+ else {
111
+ // Otherwise the type isn't inherited, so we don't need an Alias and can just store the Cpp
112
+ // pointer directory:
113
+ deallocate (v_h) = ptr;
109
114
}
110
- // Otherwise the type isn't inherited, so we don't need an Alias and can just store the Cpp
111
- // pointer directory:
112
- deallocate (v_h) = ptr;
113
115
}
114
116
115
117
// Pointer return v2: a factory that always returns an alias instance ptr. We simply take over
@@ -143,14 +145,10 @@ template <typename Class>
143
145
void construct (value_and_holder &v_h, Cpp<Class> &&result, bool need_alias) {
144
146
static_assert (std::is_move_constructible<Cpp<Class>>::value,
145
147
" pybind11::init() return-by-value factory function requires a movable class" );
146
- if (Class::has_alias && need_alias) {
147
- if (!construct_alias_from_cpp<Class>(v_h, std::move (result)))
148
- throw type_error (" pybind11::init(): unable to convert returned instance to "
149
- " required alias class: no `Alias<Class>(Class &&)` constructor available" );
150
- }
151
- else {
148
+ if (Class::has_alias && need_alias)
149
+ construct_alias_from_cpp<Class>(is_alias_constructible<Class>{}, v_h, std::move (result));
150
+ else
152
151
deallocate (v_h) = new Cpp<Class>(std::move (result));
153
- }
154
152
}
155
153
156
154
// return-by-value version 2: returning a value of the alias type itself. We move-construct an
0 commit comments