5

C++ で MessagePack を使用しており、この Python マップに相当するものを逆シリアル化しようとしています。

{'metadata': {'date': '2014-06-25', 'user_id': 501},
 'values': [3.0, 4.0, 5.0],
 'version': 1}

最上位オブジェクトは文字列キーを持つマップですが、値はまったく異なる型です。私のコードは、オブジェクトの構造がどうあるべきかを事前に知っています。整数を宣言してから、デシリアライゼーション コードに「versionキーの値は整数なので、その整数の値をこのメモリ アドレスに入れます」と伝える必要があります。</p>

問題は、私の C++ コードがこの構造をマップとして扱えるようになる方法さえわからないことです。私は次のようなことを期待します

msgpack::unpacker unpacker;
// ...copy the data into unpacker's buffer...

msgpack::unpacked message;
std::map<std::string, anything> output_map;

unpacker.next(&message);
msgpack::object obj = message.get();
obj.convert(&output_map);

int version_number = output_map.at("version");

ここで機能する可能性のあるタイプ ( anything) はありますか? MessagePack のドキュメントには簡単な例しかありません。このブログ投稿の方が優れていますが、このユース ケースについては説明していません。

4

2 に答える 2

1

これは、boost::variant を使用して行うことができます。再帰構造を実装するには、次のように oost::make_recursive_variant を使用できます。

typedef boost::make_recursive_variant<
    std::string,
    std::map<boost::recursive_variant_, boost::recursive_variant_>,
    std::vector<boost::recursive_variant_>,
    int,
    double
    >::type variant_t;

ドキュメントは次のとおりです 。 http://www.boost.org/doc/libs/1_55_0/doc/html/variant/tutorial.html#variant.tutorial.recursive.recursive-variant

また、次のように、msgpack::object から variant_t へ、またはその逆に変換するコンバーターを作成する必要があります。

// Custom converter for variant_t
namespace msgpack {

// Convert from msgpacl::object to variant_t.
inline variant_t& operator>>(object const& o, variant_t& v) {
    switch(o.type) {
    case type::MAP:
        v = std::map<variant_t, variant_t>();
        o.convert(boost::get<std::map<variant_t, variant_t> >(&v));
        break;
    case type::ARRAY:
        v = std::vector<variant_t>();
        o.convert(boost::get<std::vector<variant_t> >(&v));
        break;
    case type::POSITIVE_INTEGER:
        v = int();
        o.convert(boost::get<int>(&v));
        break;
    case type::DOUBLE:
        v = double();
        o.convert(boost::get<double>(&v));
        break;
    case type::RAW:
        v = std::string();
        o.convert(boost::get<std::string>(&v));
        break;
    default:
        break;
    }
    return v;
}


// Convert from variant_t to msgpacl::object.
template <typename Stream>
struct packer_imp:boost::static_visitor<void> {
    template <typename T>
    void operator()(T const& value) const {
        o_.pack(value);
    }
    packer_imp(packer<Stream>& o):o_(o) {}
    packer<Stream>& o_;
};

template <typename Stream>
inline packer<Stream>& operator<< (packer<Stream>& o, const variant_t& v)
{
    boost::apply_visitor(packer_imp<Stream>(o), v);
    return o;
}

} // namespace msgpack

Gist から完全なサンプル コードを取得できます: https://gist.github.com/redboltz/672c5af16b2907488977 サンプルでは C++11 機能を使用しているため、 -std=c++11 オプションを追加する必要があります。 .

于 2014-06-28T16:28:58.937 に答える
0

私はこれをパントし、独自のテキストベースのシリアライゼーション形式を作成しました。MessagePack のように一般的には有用ではありませんが、これらの静的型付けの問題について説明することができます。

于 2014-08-07T20:58:39.407 に答える