Closed ghost closed 1 year ago
a little change. I added a second default template parameter for YAML::convert so users can use SFINAE to partial specialized it. I have tested this:
template <typename T> struct convert<T, std::enable_if_t<std::is_enum_v<T>>> { static Node encode(const T &rhs) { Node node; node = std::string(enum_enhanced::enum_to_string(rhs)); return node; } static bool decode(const Node &node, T &rhs) { rhs = enum_enhanced::enum_from_string<T>(node.as<std::string>()); return true; } };
enum_enhanced::enum_to_string can convert all enum to std::string. enum_enhanced::enum_from_string<T> convert std::string to enum. It come from here:
enum_enhanced::enum_to_string
enum_enhanced::enum_from_string<T>
#pragma once #include <string> #include <type_traits> namespace enum_enhanced { namespace enum_enhanced_impl { template <class T, T N> char const *pretty_string() { #ifdef _MSC_VER return __FUNCSIG__; #else return __PRETTY_FUNCTION__; #endif } template <class T> struct PrettyStringCaller { public: int n; std::string &s; public: template <int I> void Call() const { if (n == I) s = pretty_string<T, static_cast<T>(I)>(); } }; template <int Start, int End, class F> typename std::enable_if<Start == End>::type static_for(F const &caller) { } template <int Start, int End, class F> typename std::enable_if<Start != End>::type static_for(F const &caller) { caller.template Call<Start>(); static_for<Start + 1, End>(caller); } } // namespace enum_enhanced_impl template <class T, int Start = 0, int End = 64> std::string enum_to_string(T n) { static_assert(Start < End); using namespace enum_enhanced_impl; std::string string; static_for<Start, End>(PrettyStringCaller<T>{.n = static_cast<int>(n), .s = string}); #ifdef _MSC_VER size_t end = string.find_last_of('>'); size_t start = string.find_last_of(',', end) + 1; #else size_t start = string.find("N = ") + 4; size_t end = string.find(']', start); #endif string = string.substr(start, end - start); if ((start = string.find_last_of(":")) != string.npos) { string = string.substr(start + 1, string.size() - start); } return string; } template <class T, int Start = 0, int End = 64> T enum_from_string(std::string const &str) { static_assert(Start < End); using namespace enum_enhanced_impl; for (int i = Start; i < End; i++) { if (!str.compare(enum_to_string<T, Start, End>(static_cast<T>(i)))) { return static_cast<T>(i); } } throw; } } // namespace enum_enhanced
a little change. I added a second default template parameter for YAML::convert so users can use SFINAE to partial specialized it. I have tested this:
enum_enhanced::enum_to_string
can convert all enum to std::string.enum_enhanced::enum_from_string<T>
convert std::string to enum. It come from here: