@@ -890,6 +890,77 @@ template <typename... Tuple> class type_caster<std::tuple<Tuple...>> {
890890 std::tuple<make_caster<Tuple>...> value;
891891};
892892
893+ struct py3_enum_info {
894+ handle type = {};
895+ std::unordered_map<long long , handle> values = {};
896+
897+ py3_enum_info () = default ;
898+
899+ py3_enum_info (handle type, const dict& values) : type(type) {
900+ for (auto item : values)
901+ this ->values [static_cast <long long >(item.second .cast <int >())] = type.attr (item.first );
902+ }
903+
904+ static std::unordered_map<std::type_index, py3_enum_info>& registry () {
905+ static std::unordered_map<std::type_index, py3_enum_info> map = {};
906+ return map;
907+ }
908+
909+ template <typename T>
910+ static void bind (handle type, const dict& values) {
911+ registry ()[typeid (T)] = py3_enum_info (type, values);
912+ }
913+
914+ template <typename T>
915+ static const py3_enum_info* get () {
916+ auto it = registry ().find (typeid (T));
917+ return it == registry ().end () ? nullptr : &it->second ;
918+ }
919+ };
920+
921+ template <typename T>
922+ struct type_caster <T, enable_if_t <std::is_enum<T>::value>> {
923+ private:
924+ using base_caster = type_caster_base<T>;
925+ base_caster caster;
926+ bool py3 = false ;
927+ T value;
928+
929+ public:
930+ template <typename U> using cast_op_type = pybind11::detail::cast_op_type<U>;
931+
932+ operator T*() { return py3 ? &value : static_cast <T*>(caster); }
933+ operator T&() { return py3 ? value : static_cast <T&>(caster); }
934+
935+ static handle cast (const T& src, return_value_policy rvp, handle parent) {
936+ if (auto info = py3_enum_info::get<T>()) {
937+ auto it = info->values .find (static_cast <long long >(src));
938+ if (it == info->values .end ())
939+ return {};
940+ return it->second .inc_ref ();
941+ }
942+ return base_caster::cast (src, rvp, parent);
943+ }
944+
945+ bool load (handle src, bool convert) {
946+ if (!src)
947+ return false ;
948+ if (auto info = py3_enum_info::get<T>()) {
949+ py3 = true ;
950+ if (!isinstance (src, info->type ))
951+ return false ;
952+ value = static_cast <T>(src.cast <long long >());
953+ return true ;
954+ }
955+ py3 = false ;
956+ return caster.load (src, convert);
957+ }
958+
959+ static PYBIND11_DESCR name () {
960+ return base_caster::name ();
961+ }
962+ };
963+
893964// / Helper class which abstracts away certain actions. Users can provide specializations for
894965// / custom holders, but it's only necessary if the type has a non-standard interface.
895966template <typename T>
0 commit comments