@@ -1116,24 +1116,32 @@ class class_ : public detail::generic_type {
11161116template <typename Type> class enum_ : public class_ <Type> {
11171117public:
11181118 using class_<Type>::def;
1119+ using class_<Type>::def_property_readonly_static;
11191120 using Scalar = typename std::underlying_type<Type>::type;
11201121 template <typename T> using arithmetic_tag = std::is_same<T, arithmetic>;
11211122
11221123 template <typename ... Extra>
11231124 enum_ (const handle &scope, const char *name, const Extra&... extra)
1124- : class_<Type>(scope, name, extra...), m_parent(scope) {
1125+ : class_<Type>(scope, name, extra...), m_entries(), m_parent(scope) {
11251126
11261127 constexpr bool is_arithmetic =
11271128 !std::is_same<detail::first_of_t <arithmetic_tag, void , Extra...>,
11281129 void >::value;
11291130
1130- auto entries = new std::unordered_map<Scalar, const char *>();
1131- def (" __repr__" , [name, entries](Type value) -> std::string {
1132- auto it = entries->find ((Scalar) value);
1133- return std::string (name) + " ." +
1134- ((it == entries->end ()) ? std::string (" ???" )
1135- : std::string (it->second ));
1131+ auto m_entries_ptr = m_entries.inc_ref ().ptr ();
1132+ def (" __repr__" , [name, m_entries_ptr](Type value) -> pybind11::str {
1133+ for (const auto &kv : reinterpret_borrow<dict>(m_entries_ptr)) {
1134+ if (pybind11::cast<Type>(kv.second ) == value)
1135+ return pybind11::str (" {}.{}" ).format (name, kv.first );
1136+ }
1137+ return pybind11::str (" {}.???" ).format (name);
11361138 });
1139+ def_property_readonly_static (" __members__" , [m_entries_ptr](object /* self */ ) {
1140+ dict m;
1141+ for (const auto &kv : reinterpret_borrow<dict>(m_entries_ptr))
1142+ m[kv.first ] = kv.second ;
1143+ return m;
1144+ }, return_value_policy::copy);
11371145 def (" __init__" , [](Type& value, Scalar i) { value = (Type)i; });
11381146 def (" __init__" , [](Type& value, Scalar i) { new (&value) Type ((Type) i); });
11391147 def (" __int__" , [](Type value) { return (Scalar) value; });
@@ -1172,26 +1180,25 @@ template <typename Type> class enum_ : public class_<Type> {
11721180 // Pickling and unpickling -- needed for use with the 'multiprocessing' module
11731181 def (" __getstate__" , [](const Type &value) { return pybind11::make_tuple ((Scalar) value); });
11741182 def (" __setstate__" , [](Type &p, tuple t) { new (&p) Type ((Type) t[0 ].cast <Scalar>()); });
1175- m_entries = entries;
11761183 }
11771184
11781185 // / Export enumeration entries into the parent scope
1179- enum_ &export_values () {
1180- for (auto item : reinterpret_borrow<dict>(((PyTypeObject *) this ->m_ptr )->tp_dict )) {
1181- if (isinstance (item.second , this ->m_ptr ))
1182- m_parent.attr (item.first ) = item.second ;
1183- }
1186+ enum_& export_values () {
1187+ for (const auto &kv : m_entries)
1188+ m_parent.attr (kv.first ) = kv.second ;
11841189 return *this ;
11851190 }
11861191
11871192 // / Add an enumeration entry
11881193 enum_& value (char const * name, Type value) {
1189- this ->attr (name) = pybind11::cast (value, return_value_policy::copy);
1190- (*m_entries)[(Scalar) value] = name;
1194+ auto v = pybind11::cast (value, return_value_policy::copy);
1195+ this ->attr (name) = v;
1196+ m_entries[pybind11::str (name)] = v;
11911197 return *this ;
11921198 }
1199+
11931200private:
1194- std::unordered_map<Scalar, const char *> * m_entries;
1201+ dict m_entries;
11951202 handle m_parent;
11961203};
11971204
0 commit comments