{"action":"created","issue":{"url":"https://api.github.com/repos/aantron/better-enums/issues/8","labels_url":"https://api.github.com/repos/aantron/better-enums/issues/8/labels{/name}","comments_url":"https://api.github.com/repos/aantron/better-enums/issues/8/comments","events_url":"https://api.github.com/repos/aantron/better-enums/issues/8/events","html_url":"https://github.com/aantron/better-enums/issues/8","id":102173956,"number":8,"title":"Usage inside a class","user":{"login":"X-Ryl669","id":3277165,"avatar_url":"https://avatars.githubusercontent.com/u/3277165?v=3","gravatar_id":"","url":"https://api.github.com/users/X-Ryl669","html_url":"https://github.com/X-Ryl669","followers_url":"https://api.github.com/users/X-Ryl669/followers","following_url":"https://api.github.com/users/X-Ryl669/following{/other_user}","gists_url":"https://api.github.com/users/X-Ryl669/gists{/gist_id}","starred_url":"https://api.github.com/users/X-Ryl669/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/X-Ryl669/subscriptions","organizations_url":"https://api.github.com/users/X-Ryl669/orgs","repos_url":"https://api.github.com/users/X-Ryl669/repos","events_url":"https://api.github.com/users/X-Ryl669/events{/privacy}","received_events_url":"https://api.github.com/users/X-Ryl669/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":17,"created_at":"2015-08-20T16:07:50Z","updated_at":"2015-08-20T20:07:09Z","closed_at":null,"body":"You can do something like this:\r\n```\r\n\r\n\r\n// Make sure it's possible to compare string correctly\r\nconstexpr bool static_strequal_helper(const char * a, const char * b, unsigned len) {\r\n   return (len == 0) ? true : ((*a == *b) ? static_strequal_helper(a + 1, b + 1, len - 1) : false);\r\n}\r\n\r\n// This is the base class using CRTP for capturing the enum' class type\r\n// With the macro trick below, it allow auto registration even in classes of your enum, and \r\n// also O(1) runtime string lookup-to-value matching\r\ntemplate <typename T>\r\nstruct CatalogEnum\r\n{\r\n     typedef T ClassType;\r\n     static std::map<const char *, int> enumToValue; \r\n     static void registerField(const char * name, int value) { enumToValue[name] = value; }\r\n     static int fromStringImpl(const char * name) { return enumToValue[name]; }\r\n};\r\n\r\n/* This is the basic block. Because your enum derives from CatalogEnum, it has a registerField member, so it can be registered at run time (before any usage)\r\nAlso, I've provided a basic constexpr trick to match against an enum value, but not the code \r\nfor complete lookup. \r\nIt should not be difficult to iterate over all the RegisterEnum entries at compile time to perform O(N) lookup for a fromString method. \r\nPlease notice that even if you enum as same value for 2 field, it'll generate two different instance of this\r\ntemplate, and will still work correctly, since the pointer to _get_field_name is different */ \r\ntemplate <typename Class, int value, typename const char* (*enumName)()>\r\nstruct RegisterEnum\r\n{\r\n      // Compile-time version\r\n      template<size_t N>\r\n      constexpr bool match_string(const char (&a)[N]) const { return static_strequal_helper(a, (*enumName)(), N); }\r\n      // Run-time version\r\n      bool match_string(const char* a) const { return strcmp(a, (*enumName)()) == 0; }\r\n\r\n      RegisterEnum() { CatalogEnum<Class>::registerField((*enumName)(), value); }\r\n};\r\n\r\n// Basic macro trick, it declares a static function, and uses its address as a templated differentiator\r\n// Then the templated object constructor takes care of calling the Catalog::registerField method to register \r\n// the enum field\r\n#define DeclMember(A) \\\r\n       static const char *__get##A() { return #A; } \\\r\n       RegisterEnum<ClassType, A, &__get##A> __##A;\r\n\r\n// And some of your code:\r\n#define ENUM(Name, type, A, B, C) \\\r\n    struct Name : CatalogEnum<Name> { enum Type : type { A, B, C }; \\\r\n       DeclMember(A) \\\r\n       DeclMember(B) \\\r\n       DeclMember(C) \\\r\n       static Type fromString(const char * name) { return (Type)fromStringImpl(name); } \\\r\n       template <size_t N>\r\n       static constexpr fromString(const char (&a)[N]); // Should iterate through all RegisterEnum  and call match_string(a) on them  \r\n   [your actual code here]\r\n   }; \r\n\r\n\r\n// Usage:\r\nstruct A\r\n{\r\n      ENUM(Color, int, Blue, Red, Green); // OMG, it works!\r\n\r\n     void exampleMethod() { Color::Type c = Color::fromString(\"RED\"); }\r\n};\r\n```\r\n"},"comment":{"url":"https://api.github.com/repos/aantron/better-enums/issues/comments/133156623","html_url":"https://github.com/aantron/better-enums/issues/8#issuecomment-133156623","issue_url":"https://api.github.com/repos/aantron/better-enums/issues/8","id":133156623,"user":{"login":"aantron","id":12073668,"avatar_url":"https://avatars.githubusercontent.com/u/12073668?v=3","gravatar_id":"","url":"https://api.github.com/users/aantron","html_url":"https://github.com/aantron","followers_url":"https://api.github.com/users/aantron/followers","following_url":"https://api.github.com/users/aantron/following{/other_user}","gists_url":"https://api.github.com/users/aantron/gists{/gist_id}","starred_url":"https://api.github.com/users/aantron/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/aantron/subscriptions","organizations_url":"https://api.github.com/users/aantron/orgs","repos_url":"https://api.github.com/users/aantron/repos","events_url":"https://api.github.com/users/aantron/events{/privacy}","received_events_url":"https://api.github.com/users/aantron/received_events","type":"User","site_admin":false},"created_at":"2015-08-20T20:07:09Z","updated_at":"2015-08-20T20:07:09Z","body":"Nice. It still doesn't do the hash lookup, however. Both that, and the existing code, are complicated by this kind of compile-time string:\r\n\r\n```\r\nconstexpr const char *bobby = \"bobby\";\r\nprintf(\"%u %u %u\\n\", Test<FromString(bobby)>::value, FromString(\"bobby\"), FromString(b[0]));\r\n```\r\n\r\nThat prints `0 198195889 0`. Right now, the code discriminates between string literals and other strings, but that's not exactly the same as the difference between compile-time strings and other strings."}}