Skip to content

Instantly share code, notes, and snippets.

@mistificator
Created June 18, 2026 23:13
Show Gist options
  • Select an option

  • Save mistificator/2c40242841e88709af3917f406b73a09 to your computer and use it in GitHub Desktop.

Select an option

Save mistificator/2c40242841e88709af3917f406b73a09 to your computer and use it in GitHub Desktop.
enum_magic.h
#include <iostream>
#include <string>
#include <type_traits>
struct StringRef {
const char* data;
size_t size;
constexpr StringRef() : data(""), size(0) {}
constexpr StringRef(const char* s, size_t len) : data(s), size(len) {}
constexpr StringRef(const char* s) : data(s), size(0) {
if (s) {
while (s[size] != '\0') {
size++;
}
}
}
operator std::string() const {
return std::string(data, size);
}
constexpr bool operator==(StringRef other) const {
if (size != other.size) return false;
for (size_t i = 0; i < size; ++i) {
if (data[i] != other.data[i]) return false;
}
return true;
}
constexpr bool empty() const { return size == 0; }
};
namespace EnumMagic {
template <typename T, T Value>
constexpr StringRef GetValueNameRaw() {
#if defined(__clang__) || defined(__GNUC__)
const char* name = __PRETTY_FUNCTION__;
size_t len = 0; while (name[len] != '\0') { len++; }
size_t start = len;
while (start > 0 && name[start] != ':' && name[start] != ' ') { start--; }
if (name[start] == ':') start++;
size_t end = len;
while (end > start && name[end] != ']') { end--; }
return StringRef(name + start, end - start);
#elif defined(_MSC_VER)
const char* name = __FUNCSIG__;
size_t len = 0; while (name[len] != '\0') { len++; }
size_t start = len;
while (start > 0 && name[start] != ':' && name[start] != ' ') { start--; }
if (name[start] == ':') start++;
size_t end = len;
while (end > start && name[end] != '>') { end--; }
return StringRef(name + start, end - start);
#else
return StringRef();
#endif
}
template <typename T, T Value>
constexpr bool IsValidEnum() {
StringRef name = GetValueNameRaw<T, Value>();
if (name.empty()) return false;
char first = name.data[0];
return !((first >= '0' && first <= '9') || first == '-' || first == '(');
}
constexpr int MinRange = 0;
constexpr int MaxRange = 128;
template <typename T, size_t... Is>
struct Helper {
static constexpr StringRef ToStr(T value) {
StringRef result;
int dummy[] = { 0, (static_cast<int>(value) == (MinRange + Is) && IsValidEnum<T, static_cast<T>(MinRange + Is)>()
? (result = GetValueNameRaw<T, static_cast<T>(MinRange + Is)>(), 0) : 0)... };
(void)dummy;
return result.empty() ? StringRef("Unknown", 7) : result;
}
static constexpr bool FromStr(StringRef str, T& out_value) {
bool found = false;
int dummy[] = { 0, (!found && IsValidEnum<T, static_cast<T>(MinRange + Is)>() && GetValueNameRaw<T, static_cast<T>(MinRange + Is)>() == str
? (out_value = static_cast<T>(MinRange + Is), found = true, 0) : 0)... };
(void)dummy;
return found;
}
};
template <size_t... Is> struct Seq {};
template <size_t N, size_t... Is> struct GenSeq : GenSeq<N - 1, N - 1, Is...> {};
template <size_t... Is> struct GenSeq<0, Is...> { typedef Seq<Is...> Type; };
template <typename T>
constexpr StringRef ToStr(T value) {
return ToStrImpl(value, typename GenSeq<MaxRange - MinRange>::Type());
}
template <typename T, size_t... Is>
constexpr StringRef ToStrImpl(T value, Seq<Is...>) {
return Helper<T, Is...>::ToStr(value);
}
template <typename T>
constexpr bool FromStr(StringRef str, T& out_value) {
return FromStrImpl(str, out_value, typename GenSeq<MaxRange - MinRange>::Type());
}
template <typename T, size_t... Is>
constexpr bool FromStrImpl(StringRef str, T& out_value, Seq<Is...>) {
return Helper<T, Is...>::FromStr(str, out_value);
}
}
@mistificator

Copy link
Copy Markdown
Author
int main() {
    Color c = Color::Green;

    std::string str = EnumMagic::ToStr(c); 
    std::cout << "Serialized to std::string: " << str << std::endl; // Green

    Color parsed;
    if (EnumMagic::FromStr("Blue", parsed)) {
        std::cout << "Deserialized successfully!" << std::endl;
    }
    
    std::string input = "Red";
    if (EnumMagic::FromStr(input.size() ? input.data() : "", parsed)) {
         std::cout << "Deserialized from std::string!" << std::endl;
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment