Skip to content

Commit 1cf0948

Browse files
authored
Avoid a heap allocation on every legacy py::enum_ load (#5860)
1 parent cae4ae0 commit 1cf0948

File tree

1 file changed

+15
-15
lines changed

1 file changed

+15
-15
lines changed

include/pybind11/cast.h

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -93,37 +93,37 @@ class type_caster_enum_type {
9393
if (!underlying_caster.load(src.attr("value"), convert)) {
9494
pybind11_fail("native_enum internal consistency failure.");
9595
}
96-
value = static_cast<EnumType>(static_cast<Underlying>(underlying_caster));
96+
native_value = static_cast<EnumType>(static_cast<Underlying>(underlying_caster));
97+
native_loaded = true;
9798
return true;
9899
}
99-
if (!pybind11_enum_) {
100-
pybind11_enum_.reset(new type_caster_base<EnumType>());
100+
101+
type_caster_base<EnumType> legacy_caster;
102+
if (legacy_caster.load(src, convert)) {
103+
legacy_ptr = static_cast<EnumType *>(legacy_caster);
104+
return true;
101105
}
102-
return pybind11_enum_->load(src, convert);
106+
return false;
103107
}
104108

105109
template <typename T>
106110
using cast_op_type = detail::cast_op_type<T>;
107111

108112
// NOLINTNEXTLINE(google-explicit-constructor)
109-
operator EnumType *() {
110-
if (!pybind11_enum_) {
111-
return &value;
112-
}
113-
return pybind11_enum_->operator EnumType *();
114-
}
113+
operator EnumType *() { return native_loaded ? &native_value : legacy_ptr; }
115114

116115
// NOLINTNEXTLINE(google-explicit-constructor)
117116
operator EnumType &() {
118-
if (!pybind11_enum_) {
119-
return value;
117+
if (!native_loaded && !legacy_ptr) {
118+
throw reference_cast_error();
120119
}
121-
return pybind11_enum_->operator EnumType &();
120+
return native_loaded ? native_value : *legacy_ptr;
122121
}
123122

124123
private:
125-
std::unique_ptr<type_caster_base<EnumType>> pybind11_enum_;
126-
EnumType value;
124+
EnumType native_value; // if loading a py::native_enum
125+
bool native_loaded = false;
126+
EnumType *legacy_ptr = nullptr; // if loading a py::enum_
127127
};
128128

129129
template <typename EnumType, typename SFINAE = void>

0 commit comments

Comments
 (0)