1. 程式人生 > >實現C++ 列舉反射機制

實現C++ 列舉反射機制

上一階段寫了一些功能需要列舉反射機制,但是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;
}