{"action":"created","issue":{"url":"https://api.github.com/repos/pybind/pybind11/issues/483","repository_url":"https://api.github.com/repos/pybind/pybind11","labels_url":"https://api.github.com/repos/pybind/pybind11/issues/483/labels{/name}","comments_url":"https://api.github.com/repos/pybind/pybind11/issues/483/comments","events_url":"https://api.github.com/repos/pybind/pybind11/issues/483/events","html_url":"https://github.com/pybind/pybind11/issues/483","id":187359698,"number":483,"title":"Implicit conversion from Python string to C++ enum type","user":{"login":"stukowski","id":16364980,"avatar_url":"https://avatars.githubusercontent.com/u/16364980?v=3","gravatar_id":"","url":"https://api.github.com/users/stukowski","html_url":"https://github.com/stukowski","followers_url":"https://api.github.com/users/stukowski/followers","following_url":"https://api.github.com/users/stukowski/following{/other_user}","gists_url":"https://api.github.com/users/stukowski/gists{/gist_id}","starred_url":"https://api.github.com/users/stukowski/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/stukowski/subscriptions","organizations_url":"https://api.github.com/users/stukowski/orgs","repos_url":"https://api.github.com/users/stukowski/repos","events_url":"https://api.github.com/users/stukowski/events{/privacy}","received_events_url":"https://api.github.com/users/stukowski/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":3,"created_at":"2016-11-04T15:15:32Z","updated_at":"2016-11-04T17:11:41Z","closed_at":null,"body":"Let me propose an extension:\r\nSometimes it would be nice if a string could be passed from a Python script to a C++ function where an `enum` parameter is expected. For example:\r\n\r\n```c++\r\nstruct Pet {\r\n    enum Kind {\r\n        Dog = 0,\r\n        Cat\r\n    };\r\n    Pet(Kind type) : type(type) { }\r\n    Kind type;\r\n};\r\n```\r\n\r\nBinding code:\r\n```c++\r\nauto pet = py::class_<Pet>(m, \"Pet\")\r\n    .def(py::init<Pet::Kind>());\r\n\r\npy::enum_<Pet::Kind>(pet, \"Kind\")\r\n    .value(\"Dog\", Pet::Kind::Dog)\r\n    .value(\"Cat\", Pet::Kind::Cat);\r\n```\r\n\r\nPython:\r\n```python\r\n>>> p = Pet(Pet.Cat) # Works\r\n>>> p = Pet(\"Cat\")   # Would like to make this work too\r\n```\r\n\r\nIn principle it is possible to add optional support for this implicit conversion from a Python string to the enum type. I propose to add the following method to the ``pybind11::enum_`` class:\r\n\r\n```c++\r\ntemplate <typename Type> class enum_ : public class_<Type> {\r\n    ...\r\n\r\n    /// Set up atomatic Python string -> C++ enum conversion.\r\n    enum_& enable_conversion_from_string() {\r\n        auto entries = m_entries;\r\n\tdef(\"__init__\", [entries](Type& v, const char* str) {\r\n            for(const auto& item : *entries) {\r\n                if(!strcmp(str, item.second)) {\r\n                    v = (Type)item.first;\r\n                    return;\r\n                }\r\n            }\r\n            std::string tname = typeid(Type).name();\r\n            detail::clean_type_id(tname);\r\n            throw value_error(\"\\\"\" + std::string(str) + \"\\\" is not a valid value for enum type \" + tname);\r\n        });\r\n\timplicitly_convertible<str, Type>();\r\n        return *this;\r\n    }\r\n    ...\r\n}\r\n```\r\n\r\nThis would allow writing binding codes like this:\r\n```c++\r\npy::enum_<Pet::Kind>(pet, \"Kind\")\r\n    .value(\"Dog\", Pet::Kind::Dog)\r\n    .value(\"Cat\", Pet::Kind::Cat)\r\n    .enable_conversion_from_string();\r\n```\r\n\r\nThere is only one problem with this solution: The exception thrown by the conversion constructor when the string does not match any of the enum entries is swallowed by pybind11. Instead, a general cast error is raised because the conversion from string to the enum type failed.\r\n\r\nI am wondering what you think about this idea. Does it make sense to offer an automatic conversion like this? At least in my project there is one situation where an automatic conversion from a string is desirable.\r\n\r\nBy the way: The ``pybind11::enum_`` class constructor registers two ``__init__`` methods: One initializing the value via assignment, the other via in-place new. I think one of them is redundant. Furthermore, I noticed that the ``std::unordered_map`` allocated by the constructor is never freed. Does it make sense to use a ``shared_ptr<unordered_map>`` here so that the map gets destroyed eventually?"},"comment":{"url":"https://api.github.com/repos/pybind/pybind11/issues/comments/258491494","html_url":"https://github.com/pybind/pybind11/issues/483#issuecomment-258491494","issue_url":"https://api.github.com/repos/pybind/pybind11/issues/483","id":258491494,"user":{"login":"jagerman","id":4459524,"avatar_url":"https://avatars.githubusercontent.com/u/4459524?v=3","gravatar_id":"","url":"https://api.github.com/users/jagerman","html_url":"https://github.com/jagerman","followers_url":"https://api.github.com/users/jagerman/followers","following_url":"https://api.github.com/users/jagerman/following{/other_user}","gists_url":"https://api.github.com/users/jagerman/gists{/gist_id}","starred_url":"https://api.github.com/users/jagerman/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jagerman/subscriptions","organizations_url":"https://api.github.com/users/jagerman/orgs","repos_url":"https://api.github.com/users/jagerman/repos","events_url":"https://api.github.com/users/jagerman/events{/privacy}","received_events_url":"https://api.github.com/users/jagerman/received_events","type":"User","site_admin":false},"created_at":"2016-11-04T17:11:41Z","updated_at":"2016-11-04T17:11:41Z","body":"(I'd also suggest you code this up, add some tests for it, and submit a PR--it'll make it a bit easier to discuss the code and see it in action)."}}
{"actor":{"display_login":"jagerman"}}