由于已经有了boost::to_string,所以还要写一个from_string的辅助函数,代码如下:
//1.
template
struct FromString {
static const char* type() { return "Generic"; }
static void from_string(T& dest, const std::string& source)
{
try
{
dest = boost::lexical_cast(source);
}
catch (boost::bad_lexical_cast& e)
{
std::cerr << "bad_lexical_cast:"<(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
void from_string(T& expected, const std::string& str_value) {
std::cerr << expected << " type " << FromString::type();
FromString::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 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 {
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(sizeof(dest), source.size()));
}
}
};