4

次のサンプルはコンパイルされません。

In file included from /usr/include/msgpack.hpp:18:
/usr/include/msgpack/object.hpp:211:3: error: member reference base type 'logd::log_level' is not a structure or union

および他の列挙型クラスの対応するエラー。私の質問は、msgpack の c++ api を使用して、c++11enum class型のメンバーを持つクラスをシリアル化する方法です。

#ifndef LOG_MSG_HPP_
#define LOG_MSG_HPP_

#include <stdlib.h>
#include <msgpack.hpp>

/** @namespace logd */
namespace logd {

enum class log_level { SILENT,... DEBUG };

enum class log_domain { AI, ...  MISC };

class log_msg {
    public:
        log_msg(log_level lev, log_domain dom, std::string msg);
        log_level level();
        log_domain domain();
        std::string message();
        ~log_msg();
        MSGPACK_DEFINE(lev_, dom_, msg_);

    private:
        log_msg();
        log_level   lev_ {log_level::DEBUG};
        log_domain  dom_ {log_domain::MISC};
        std::string msg_ {"No message given."};
};
} /* namespace logd */
#endif /* LOG_MSG_HPP_ */

: 列挙型は私のものなので、msgpack を満足させるように喜んで変更できます。残念ながら、彼らのドキュメントや Google の最初の数ページには、この件に関する参考文献は見つかりません。私はC ++にかなり慣れていないため、ヘッダー/ソースを読んで何をすべきかを判断することもできません。

4

3 に答える 3

6

MSGPACK_ADD_ENUM() マクロを使用できます。バージョン 1.0.0 からサポートされています。バージョン 1.1.0 以降を推奨します。

参照: https://github.com/msgpack/msgpack-c/wiki/v1_1_cpp_adaptor#enums

あなたのコードに MSGPACK_ADD_ENUM() を適用しました:

#ifndef LOG_MSG_HPP_
#define LOG_MSG_HPP_

#include <stdlib.h>
#include <msgpack.hpp>

/** @namespace logd */
namespace logd {

enum class log_level { SILENT,DEBUG };

enum class log_domain { AI, MISC };

class log_msg {
    public:
        log_msg(log_level lev, log_domain dom, std::string msg):lev_(lev), dom_(dom), msg_(msg) {}
        log_level level() { return lev_;}
        log_domain domain() { return dom_;}
        std::string message() { return msg_; }
        ~log_msg() {}
        MSGPACK_DEFINE(lev_, dom_, msg_);
        log_msg() = default;

    private:
        log_level   lev_ {log_level::DEBUG};
        log_domain  dom_ {log_domain::MISC};
        std::string msg_ {"No message given."};
};
} /* namespace logd */

MSGPACK_ADD_ENUM(logd::log_level);
MSGPACK_ADD_ENUM(logd::log_domain);


#endif /* LOG_MSG_HPP_ */

#include <sstream>
#include <cassert>

int main() {
    logd::log_msg lm { logd::log_level::SILENT, logd::log_domain::AI, "hello" };
    std::stringstream ss;
    msgpack::pack(ss, lm);

    msgpack::object obj = msgpack::unpack(ss.str().data(), ss.str().size()).get();
    logd::log_msg lm2 = obj.as<logd::log_msg>();
    assert(lm.level() == lm2.level());
    assert(lm.domain() == lm2.domain());
    assert(lm.message() == lm2.message());
}
于 2015-04-14T02:49:33.507 に答える
0

うまくいくように見える1つの方法は、列挙型をユニオンでラップすることです...

union log_level_t {
    log_level lev;
    int       levint;
}

...

    log_level_t lev_;

...

MSGPACK_DEFINE(lev_.levint, dom_.domint, msg);

これはくだらないアプローチのように思えますが、うまくいきます。

于 2013-11-23T01:33:15.713 に答える
0

おそらくもう少しエレガントな別の解決策を見つけました(わかりました、それほど完璧ではありません):

MSGPACK_DEFINE((int&)lev_, (int&)dom_, msg)

したがって、新しいユニオンを作成せずに元の列挙型を保持できます。

逆シリアル化メソッドは問題なく機能するはずです。

于 2015-04-03T16:05:44.697 に答える