Enable comparisons between enums and their underlying types

This commit is contained in:
Pim Schellart 2016-08-02 10:58:32 -04:00
parent 2160860c0a
commit e5b42ef1fe
3 changed files with 39 additions and 8 deletions

View File

@ -46,6 +46,22 @@ print("Inequality test 2: " + str(
ExampleWithEnum.test_function(ExampleWithEnum.EFirstMode) != ExampleWithEnum.test_function(ExampleWithEnum.EFirstMode) !=
ExampleWithEnum.test_function(ExampleWithEnum.ESecondMode))) ExampleWithEnum.test_function(ExampleWithEnum.ESecondMode)))
print("Equality test 3: " + str(
ExampleWithEnum.test_function(ExampleWithEnum.EFirstMode) ==
int(ExampleWithEnum.test_function(ExampleWithEnum.EFirstMode))))
print("Inequality test 3: " + str(
ExampleWithEnum.test_function(ExampleWithEnum.EFirstMode) !=
int(ExampleWithEnum.test_function(ExampleWithEnum.EFirstMode))))
print("Equality test 4: " + str(
ExampleWithEnum.test_function(ExampleWithEnum.EFirstMode) ==
int(ExampleWithEnum.test_function(ExampleWithEnum.ESecondMode))))
print("Inequality test 4: " + str(
ExampleWithEnum.test_function(ExampleWithEnum.EFirstMode) !=
int(ExampleWithEnum.test_function(ExampleWithEnum.ESecondMode))))
x = { x = {
ExampleWithEnum.test_function(ExampleWithEnum.EFirstMode): 1, ExampleWithEnum.test_function(ExampleWithEnum.EFirstMode): 1,
ExampleWithEnum.test_function(ExampleWithEnum.ESecondMode): 2 ExampleWithEnum.test_function(ExampleWithEnum.ESecondMode): 2

View File

@ -30,6 +30,18 @@ ExampleWithEnum::test_function(enum=1)
ExampleWithEnum::test_function(enum=2) ExampleWithEnum::test_function(enum=2)
Inequality test 2: True Inequality test 2: True
ExampleWithEnum::test_function(enum=1) ExampleWithEnum::test_function(enum=1)
ExampleWithEnum::test_function(enum=1)
Equality test 3: True
ExampleWithEnum::test_function(enum=1)
ExampleWithEnum::test_function(enum=1)
Inequality test 3: False
ExampleWithEnum::test_function(enum=1)
ExampleWithEnum::test_function(enum=2)
Equality test 4: False
ExampleWithEnum::test_function(enum=1)
ExampleWithEnum::test_function(enum=2)
Inequality test 4: True
ExampleWithEnum::test_function(enum=1)
ExampleWithEnum::test_function(enum=2) ExampleWithEnum::test_function(enum=2)
ExampleWithEnum::test_function(enum=1) ExampleWithEnum::test_function(enum=1)
ExampleWithEnum::test_function(enum=2) ExampleWithEnum::test_function(enum=2)

View File

@ -1004,22 +1004,25 @@ private:
/// Binds C++ enumerations and enumeration classes to Python /// Binds C++ enumerations and enumeration classes to Python
template <typename Type> class enum_ : public class_<Type> { template <typename Type> class enum_ : public class_<Type> {
public: public:
using UnderlyingType = typename std::underlying_type<Type>::type;
template <typename... Extra> template <typename... Extra>
enum_(const handle &scope, const char *name, const Extra&... extra) enum_(const handle &scope, const char *name, const Extra&... extra)
: class_<Type>(scope, name, extra...), m_parent(scope) { : class_<Type>(scope, name, extra...), m_parent(scope) {
auto entries = new std::unordered_map<int, const char *>(); auto entries = new std::unordered_map<UnderlyingType, const char *>();
this->def("__repr__", [name, entries](Type value) -> std::string { this->def("__repr__", [name, entries](Type value) -> std::string {
auto it = entries->find((int) value); auto it = entries->find((UnderlyingType) value);
return std::string(name) + "." + return std::string(name) + "." +
((it == entries->end()) ? std::string("???") ((it == entries->end()) ? std::string("???")
: std::string(it->second)); : std::string(it->second));
}); });
this->def("__init__", [](Type& value, int i) { value = (Type)i; }); this->def("__init__", [](Type& value, UnderlyingType i) { value = (Type)i; });
this->def("__init__", [](Type& value, int i) { new (&value) Type((Type) i); }); this->def("__init__", [](Type& value, UnderlyingType i) { new (&value) Type((Type) i); });
this->def("__int__", [](Type value) { return (int) value; }); this->def("__int__", [](Type value) { return (UnderlyingType) value; });
this->def("__eq__", [](const Type &value, Type *value2) { return value2 && value == *value2; }); this->def("__eq__", [](const Type &value, Type *value2) { return value2 && value == *value2; });
this->def("__eq__", [](const Type &value, UnderlyingType value2) { return value2 && value == value2; });
this->def("__ne__", [](const Type &value, Type *value2) { return !value2 || value != *value2; }); this->def("__ne__", [](const Type &value, Type *value2) { return !value2 || value != *value2; });
this->def("__hash__", [](const Type &value) { return (int) value; }); this->def("__ne__", [](const Type &value, UnderlyingType value2) { return value != value2; });
this->def("__hash__", [](const Type &value) { return (UnderlyingType) value; });
m_entries = entries; m_entries = entries;
} }
@ -1036,11 +1039,11 @@ public:
/// Add an enumeration entry /// Add an enumeration entry
enum_& value(char const* name, Type value) { enum_& value(char const* name, Type value) {
this->attr(name) = pybind11::cast(value, return_value_policy::copy); this->attr(name) = pybind11::cast(value, return_value_policy::copy);
(*m_entries)[(int) value] = name; (*m_entries)[(UnderlyingType) value] = name;
return *this; return *this;
} }
private: private:
std::unordered_map<int, const char *> *m_entries; std::unordered_map<UnderlyingType, const char *> *m_entries;
handle m_parent; handle m_parent;
}; };