Skip to content

Commit

Permalink
Move most of py3 enum impl into the type caster
Browse files Browse the repository at this point in the history
  • Loading branch information
aldanor committed Apr 6, 2017
1 parent c5b5b58 commit fc629e2
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 33 deletions.
55 changes: 25 additions & 30 deletions include/pybind11/cast.h
Original file line number Diff line number Diff line change
Expand Up @@ -890,52 +890,45 @@ template <typename... Tuple> class type_caster<std::tuple<Tuple...>> {
std::tuple<make_caster<Tuple>...> value;
};

template<typename U>
struct py3_enum_info {
handle type = {};
std::unordered_map<long long, handle> values = {};
std::unordered_map<U, handle> values = {};

py3_enum_info() = default;

py3_enum_info(handle type, const dict& values) : type(type) {
for (auto item : values)
this->values[static_cast<long long>(item.second.cast<int>())] = type.attr(item.first);
}

static std::unordered_map<std::type_index, py3_enum_info>& registry() {
static std::unordered_map<std::type_index, py3_enum_info> map = {};
return map;
}

template<typename T>
static void bind(handle type, const dict& values) {
registry()[typeid(T)] = py3_enum_info(type, values);
}

template<typename T>
static const py3_enum_info* get() {
auto it = registry().find(typeid(T));
return it == registry().end() ? nullptr : &it->second;
for (auto item : values) {
this->values[item.second.cast<U>()] = type.attr(item.first);
}
}
};

template<typename T>
struct type_caster<T, enable_if_t<std::is_enum<T>::value>> {
using underlying_type = typename std::underlying_type<T>::type;

private:
using base_caster = type_caster_base<T>;

static std::unique_ptr<py3_enum_info<underlying_type>>& py3_info() {
static std::unique_ptr<py3_enum_info<underlying_type>> info;
return info;
}

base_caster caster;
bool py3 = false;
T value;

public:
template<typename U> using cast_op_type = pybind11::detail::cast_op_type<U>;

operator T*() { return py3 ? &value : static_cast<T*>(caster); }
operator T&() { return py3 ? value : static_cast<T&>(caster); }
operator T*() { return py3_info() ? &value : static_cast<T*>(caster); }
operator T&() { return py3_info() ? value : static_cast<T&>(caster); }

static handle cast(const T& src, return_value_policy rvp, handle parent) {
if (auto info = py3_enum_info::get<T>()) {
auto it = info->values.find(static_cast<long long>(src));
if (it == info->values.end())
if (py3_info()) {
auto it = py3_info()->values.find(static_cast<underlying_type>(src));
if (it == py3_info()->values.end())
return {};
return it->second.inc_ref();
}
Expand All @@ -945,20 +938,22 @@ struct type_caster<T, enable_if_t<std::is_enum<T>::value>> {
bool load(handle src, bool convert) {
if (!src)
return false;
if (auto info = py3_enum_info::get<T>()) {
py3 = true;
if (!isinstance(src, info->type))
if (py3_info()) {
if (!isinstance(src, py3_info()->type))
return false;
value = static_cast<T>(src.cast<long long>());
value = static_cast<T>(src.cast<underlying_type>());
return true;
}
py3 = false;
return caster.load(src, convert);
}

static PYBIND11_DESCR name() {
return base_caster::name();
}

static void bind(handle type, const dict& values) {
py3_info().reset(new py3_enum_info<underlying_type>(type, values));
}
};

/// Helper class which abstracts away certain actions. Users can provide specializations for
Expand Down
6 changes: 3 additions & 3 deletions include/pybind11/pybind11.h
Original file line number Diff line number Diff line change
Expand Up @@ -1243,8 +1243,8 @@ class py3_enum {
public:
using underlying_type = typename std::underlying_type<T>::type;

py3_enum(handle scope, const char* name)
: name(name),
py3_enum(handle scope, const char* enum_name)
: name(enum_name),
parent(scope),
ctor(module::import("enum").attr("IntEnum")),
unique(module::import("enum").attr("unique")) {
Expand All @@ -1267,7 +1267,7 @@ class py3_enum {
void update() {
object type = unique(ctor(name, entries));
setattr(parent, name, type);
detail::py3_enum_info::bind<T>(type, entries);
detail::type_caster<T>::bind(type, entries);
}
};

Expand Down

0 comments on commit fc629e2

Please sign in to comment.