工作中经常遇到在枚举编码与字符串形式转换的需求,写一个模板类来实现该功能。
理想情况下,字符串的类型最好自动推导,但尝试用auto function() ->decltype()的方法实现总是提示语法错误无法编译,留待将来解决,现暂用模板参数实现。
1 #ifndef DEFINITIONWRAP_H 2 #define DEFINITIONWRAP_H 3 4 #include <string> 5 #include <vector> 6 #include <map> 7 #include <optional> 8 #include <algorithm> 9 #include <cassert> 10 11 namespace Framework::Core{ 12 //The template class is used to wrap a enumeration class to help it convert between characters and encoding forms. 13 //You can define the enumeration class as a struct or class forms, but it must be conform the following conditions: 14 //The enumeration class must be has a static map class member variable named codeStrings to store the mapping relationship of coding to the string. 15 //The enumeration class example: 16 /* 17 //define: 18 struct ExampleDefiniation 19 { 20 enum Code{ 21 Code1 22 , Code2 23 }; 24 25 static const std::map<Code, std::wstring> codeStrings; 26 }; 27 28 const std::map<Code, std::wstring> Example::codeStrings{ 29 {Exmaple::Code1, L"CodeString1"} 30 ,{Example::Code2, L"CodeString2"} 31 }; 32 using Example = DefinitionWrap<ExampleDefinition, ExampleDefiniation::Code1>; 33 34 //using 35 auto code1{L"CodeString1"}; 36 auto code2{Example::Definition::Code2}; 37 Exmaple::Definition code1Val{code1}; 38 std::wstring codeStr2{code2}; 39 */ 40 template <typename T, typename T::Code defCode, typename StringType=std::wstring> 41 class DefinitionWrap 42 { 43 public: 44 using Definition = typename T::Code; 45 46 static std::optional<StringType> toString(const Definition& code) { 47 const auto it{ T::codeStrings.find(code) }; 48 if (it != T::codeStrings.cend()) { 49 return it->second; 50 } 51 return {}; 52 } 53 54 static std::optional<Definition> toCode(const StringType& str) { 55 const auto it = std::find_if(T::codeStrings.cbegin(), T::codeStrings.cend(), [str](auto &val) {return val.second == str;}); 56 if (it != T::codeStrings.cend()) { 57 return it->first; 58 } 59 return {}; 60 } 61 static std::vector<StringType> getDefinitionStrings(void) { 62 std::vector<StringType> strings; 63 std::for_each(T::codeStrings.cbegin(), T::codeStrings.cend(), [&](const auto &item){strings.emplace_back(item.second);}); 64 return strings; 65 } 66 static std::vector<Definition> getDefinitionCodes(void){ 67 std::vector<Definition> codes; 68 std::for_each(T::codeStrings.cbegin(), T::codeStrings.cend(), [&](const auto &item){codes.emplace_back(item.first);}); 69 return codes; 70 } 71 static bool isValidDefinitionCode(const int code){ 72 auto codes{getDefinitionCodes()}; 73 return std::find_if(codes.begin(), codes.end(), [code](auto i){return static_cast<int>(i)==code;})!=codes.end(); 74 } 75 static bool isValidDefinitionString(const StringType str){ 76 return static_cast<bool>(toCode(str)); 77 } 78 79 explicit DefinitionWrap(const int& code) { 80 operator=(code); 81 } 82 DefinitionWrap(const Definition& code = defCode) : codeValue(code) {} 83 DefinitionWrap(const StringType& str) { 84 operator=(str); 85 } 86 DefinitionWrap(const DefinitionWrap& ins) : codeValue(ins.codeValue) {} 87 88 bool operator ==(const DefinitionWrap& ins) const { 89 return codeValue == ins.codeValue; 90 } 91 bool operator ==(const Definition& code) const { 92 return codeValue == code; 93 } 94 bool operator !=(const DefinitionWrap& ins) const { 95 return codeValue != ins.codeValue; 96 } 97 bool operator !=(const Definition& code) const { 98 return codeValue != code; 99 } 100 bool operator <(const DefinitionWrap& ins) const { 101 return codeValue<ins.codeValue; 102 } 103 104 DefinitionWrap &operator=(const Definition& code) { 105 codeValue = code; 106 return *this; 107 } 108 DefinitionWrap &operator=(const StringType &str) { 109 codeValue = toCode(str); 110 assert(codeValue); 111 return *this; 112 } 113 DefinitionWrap &operator=(const int value) { 114 if (isValidDefinitionCode(value)) 115 { 116 codeValue = static_cast<Definition>(value); 117 } 118 else 119 { 120 assert(false); 121 codeValue.reset(); 122 } 123 return *this; 124 } 125 126 operator StringType() const { 127 assert(codeValue); 128 return toString(*codeValue).value(); 129 } 130 operator Definition() const { 131 assert(codeValue); 132 return codeValue.value(); 133 } 134 135 protected: 136 std::optional<Definition> codeValue{ defCode }; 137 }; 138 139 //template <typename T, typename StringType> 140 //decltype(DefinitionWrap::DefinitionStrings) DefinitionWrap<T, StringType>::DefinitionStrings{ T::codeStrings }; 141 } 142 143 #endif // DEFINITIONWRAP_H