實現C++ 列舉反射機制
阿新 • • 發佈:2019-01-23
上一階段寫了一些功能需要列舉反射機制,但是C++不支援,很無奈。最近又遇到這個問題,所以自己實現了一版,
自己的版本 列舉定義是 巨集定義,其他的都是一些解析
程式碼如下:
第一次貼程式碼,也不太會
//enum_map.h標頭檔案
</pre><p><pre name="code" class="cpp">//實現 列舉反射機制 /*************************************************************** * example: * -----main.cpp * * #include "enum_map.h" * //定義列舉: * enum_define( _myEnum, //列舉名稱 * * _A_1dddd3 = 1000, //列舉值 * _A_1dddd32 , * _A_1dddd34 = 11000, * _A_1dddd35 = 1200, * __sdfsdf_AD_4 = 0xAdef12, * _Asdfsdfdd = 01232 * ) * * //std::string toStringByEnumValue(enum_name,enum_value_int); * //此函式返回列舉string型別 * //@enum_name 輸入列舉名稱 必須用上面定義型別定義 * //@enum_value_int 輸入列舉欄位實際int值 * //return string列舉欄位名稱 * * //呼叫 * int main() * { * printf("%s\n", toStringByEnumValue(_myEnum, 1300l).c_str()); * printf("%s\n", toStringByEnumValue(_myEnum, 1200).c_str()); * printf("%s\n", toStringByEnumValue(_myEnum+, 1000).c_str()); * return 0; * } * **************************************************************************/ #ifndef _enum_map_h_h #define _enum_map_h_h #include <stdarg.h> #include <string> #include <map> #include <vector> typedef std::map<int, std::string> enum_map; typedef std::map<std::string, enum_map> enum_map_list; extern enum_map_list all_enum_map_list; std::string TostringByValue(const std::string enum_name, const std::string cs_enum_info, const int enum_value); #define enum_define(enum_name,...)\ enum enum_name{\ __VA_ARGS__\ };\ const char enum_str_##enum_name[] = #__VA_ARGS__; #define toString(value_) #value_ #define toStringByEnumValue(enum_name,enum_value) TostringByValue(#enum_name,enum_str_##enum_name,enum_value) #endif
//原始檔
#include "enum_map.h" #include <stdio.h> enum_map_list all_enum_map_list; //去空格 std::string earse_spel(const std::string& str) { if (str.empty()) return std::string(""); std::string tmpStr; for (int i = 0; i < str.length(); i++) if (str[i] != ' ') tmpStr += str[i]; return tmpStr; } bool parse_enum_str(const std::string& enum_str, enum_map& enumKeyValueList) { std::vector<std::string> enum_value_list; //解析列舉逗號分隔符 size_t npos = enum_str.find(","); size_t nlastpos = 0; while (npos != std::string::npos) { enum_value_list.push_back(enum_str.substr(nlastpos, npos - nlastpos)); nlastpos = npos + 1; npos = enum_str.find(",", static_cast<unsigned int>(nlastpos)); } if (nlastpos != enum_str.length()) { enum_value_list.push_back(enum_str.substr(nlastpos, enum_str.length() - nlastpos)); } if (enum_value_list.size() == 0) return false; //解析單個列舉值對應的名稱與值 enumKeyValueList.clear(); int nDefaultValue = 0; for (std::vector<std::string>::iterator itor = enum_value_list.begin(); itor != enum_value_list.end(); itor++) { std::string str_enum_field = earse_spel(*itor);//去空格 long nEnumValue; std::string str_enum_field_name; //解析出列舉值對應的名稱與值 int nPos = str_enum_field.find("="); if (nPos != std::string::npos)//檢測是否預設值 { char tmpKeyValue[64] = {'\0'}; std::string tmpValue_; str_enum_field_name = str_enum_field.substr(0, nPos - 1); tmpValue_ = str_enum_field.substr(nPos + 1, (*itor).length()); sscanf(tmpValue_.c_str(), "%[^LlUu]", tmpKeyValue);//去enum值 後面字尾 tmpValue_ = tmpKeyValue; if (tmpValue_.find("0x") != std::string::npos) nEnumValue = strtol(tmpKeyValue, NULL,16); else if(tmpValue_[0] == '0') nEnumValue = strtol(tmpKeyValue, NULL, 8); else nEnumValue = strtol(tmpKeyValue, NULL, 10); } else { str_enum_field_name = str_enum_field; nEnumValue = nDefaultValue; } nDefaultValue = nEnumValue + 1; enumKeyValueList[nEnumValue] = str_enum_field_name; } if (enumKeyValueList.size() == 0) return false; return true; } std::string TostringByValue(const std::string enum_name, const std::string cs_enum_info, const int enum_value) { enum_map_list::iterator itor = all_enum_map_list.find(enum_name); if (itor == all_enum_map_list.end()) { enum_map enumKeyValueList; if (!parse_enum_str(cs_enum_info, enumKeyValueList)) { return std::string(""); } else { all_enum_map_list[enum_name] = enumKeyValueList; } itor = all_enum_map_list.find(enum_name); if (itor == all_enum_map_list.end()) return std::string(""); } enum_map::iterator it = itor->second.find(enum_value); if (it == itor->second.end()) return std::string(""); else return it->second; }