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の補助関数です.コードは次のとおりです.
次にmapをkeyを介して構造体の対応する名前のフィールドを見つけ、boost.を使用してこの値を支払う.pp
上の考えがはっきりしていれば、構造体の各フィールドをmapに埋め込むのはかなりはっきりしています.
mapを構造体に変換する前に、0をクリアする必要があります.そうしないと、テンプレートのマッチングが正しくない可能性があります.
最後にこのフレームワークに対してbool値を特化し、以下の文字はtrue:“1”,“t”,“true”,“yes”,or“y”とされ、その他はfalseである.
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()));
}
}
};