STD::MAP与结构体的互转

问题描述大概如下,一个已经存在的库a.lib,和服务器通信,全是通过结构体,或者基本数据类型进行的,现在额另外一个框架f,提供了c++和js交 互的方法,但只支持基本数据类型,std 容器,js里面的对象被映射成std::map<string,string>供c++层访问,现在需要通过JS调用a.lib的接口,所以 自然想到的是,做一个中间层,把map转换成struct,还好,a.lib要求的结构体非常简单,所有成员只包括基本数据类型,或者char 数组,并且,不含内嵌结构体

由于已经有了boost::to_string,所以还要写一个from_string的辅助函数,代码如下:

//1.
template <typename T>
struct FromString {
	static const char* type() { return "Generic"; }
	static void from_string(T& dest, const std::string& source)
	{
		try
		{
			dest = boost::lexical_cast<T>(source);
		}
		catch (boost::bad_lexical_cast& e)
		{
			std::cerr << "bad_lexical_cast:"<<e.what() << std::endl;
			memcpy(&dest, source.c_str(), std::min<std::size_t>(sizeof(dest), source.size()));
		}
	}
};

//2.
template <>
struct FromString < char* > {
	static const char* type() { return "char*"; }
	static void from_string(char* dest, const std::string& source)
	{
		memset(dest, 0, sizeof(dest));
		memcpy(dest, source.data(), source.size());
	}
};
//3.
template< std::size_t N >
struct FromString < char[N] > {
	static const char* type() { return "char[N]"; }
	static void from_string(char dest[N], const std::string& source)
	{
		memset(dest, 0, sizeof(dest));
		memcpy(dest, source.data(), source.size());
	}
};
template<>
struct FromString < char[10] > {
	static const char* type() { return "char[10]"; }
	static void from_string(char dest[10], const std::string& source)
	{
		memset(dest, 0, sizeof(dest));
		memcpy(dest, source.data(), source.size());
	}
};
//4.
template <>
struct FromString < char[] > {
	static const char* type() { return "char[]"; }
	static void from_string(char dest[], const std::string& source)
	{
		memset(dest, 0, sizeof(dest));
		memcpy(dest, source.data(), source.size());
	}
};

template <typename T>
void from_string(T& expected, const std::string& str_value) {
	std::cerr << expected << " type " << FromString<T>::type();
	FromString<T>::from_string(expected, str_value);
	std::cerr << expected << std::endl;
}

然后是要将map通过key,找到结构体的对应名称的字段,然后把这个值付给它,这里用了boost.pp

只要上面的思路搞清楚了,将结构体的每个字段填充到map里面就相当清晰了

#define DEF_MEMBER2( r, data, elem ) std::string BOOST_PP_CAT(key_,elem) = BOOST_PP_STRINGIZE(elem); \
std::string BOOST_PP_CAT(val_,elem) = boost::to_string(data->elem);
#define DEF_ASSIGN2( r, data, elem ) data[BOOST_PP_CAT(key_,elem)] = BOOST_PP_CAT(val_,elem);
#define MEMBERS2MAP(st,map_data, members )         \
do{                                          \
if(!st) break;                               \
BOOST_PP_SEQ_FOR_EACH( DEF_MEMBER2 ,st, members )\
BOOST_PP_SEQ_FOR_EACH( DEF_ASSIGN2,map_data, members )\
}while(0)
下面是如何使用:注意map转换成结构体之前,必须要清0,否则将有可能导致模板匹配不正确
struct test_st
{
	
	int a;
	int b;
	int c;
	float d;
	char e[32];
	char f;
};
int main(int argc, char *argv[])
{
test_st st1;
memset(&st1, 0, sizeof(st1));
std::map<std::string, std::string> containe;
boost::assign::insert(containe)("a", "1")("b", "2")("c", "3")("d", "4.2")("e", "aabc")("f","x");
MAP2MEMBERS(&st1, containe, (a)(b)(c)(d)(e)(f));
std::cout << "st1.a=" << st1.a << std::endl
<< "st1.b=" << st1.b << endl
<< "st1.c=" << st1.c << endl
<< "st1.d=" << st1.d << endl
<< "st1.e=" << st1.e << endl
<< "st1.f=" << st1.f << endl;
return 0;
}
最后还要针对这个框架,为bool值再做一个特化版本,以下字符被认为是true:”1″, “t”, “true”, “yes”, or “y”,其他的都是false

template <>
struct FromString<bool> {
	static const char* type() { return "Boolean"; }
	static void from_string(bool& dest, const std::string& source)
	{
		try
		{
			static string  true_strs[] = { "1","t","true","yes","y" };
			if (std::find(true_strs, true_strs + 5, source) != (true_strs + 5))
			{
				dest = true;
			}
			else
			{
				dest = false;
			}
		}
		catch (boost::bad_lexical_cast& e)
		{
			std::cerr << "bad_lexical_cast:" << e.what() << std::endl;
			memcpy(&dest, source.c_str(), std::min<std::size_t>(sizeof(dest), source.size()));
		}
	}
};




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值