std::MAPと構造体の相互回転

4652 ワード

問題の説明は、既存のライブラリa.libとサーバとの通信は、すべて構造体、または基本データ型によって行われ、現在は別のフレームワークfが割り当てられ、c++とjsの相互接続方法が提供されているが、基本データ型のみがサポートされ、stdコンテナ、jsの中のオブジェクトはstd::mapがc++層にアクセスするためにマッピングされ、JSでa.libのインタフェースを呼び出す必要があるので、当然考えられるのは、中間層を作ってmapをstructに変換することです.まあ、a.libが要求する構造体は非常に簡単で、すべてのメンバーは基本データ型、char配列しか含まれていません.また、埋め込み構造体は含まれていません.
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<: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 {
	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<:size_t>(sizeof(dest), source.size()));
		}
	}
};