以下示例无法编译,抱怨
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 ++ 11 enum 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 ++很新。
答案 0 :(得分:3)
您可以使用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());
}
答案 1 :(得分:0)
似乎有效的一种方法是将枚举包装在一个联合中......
union log_level_t {
log_level lev;
int levint;
}
...
log_level_t lev_;
...
MSGPACK_DEFINE(lev_.levint, dom_.domint, msg);
这似乎是一种糟糕的方法,但它确实有效。
答案 2 :(得分:0)
我找到了另一个解决方案,也许更优雅一点(好吧,它不是那么完美):
MSGPACK_DEFINE((int&)lev_, (int&)dom_, msg)
因此,您可以在不创建新联盟的情况下保留原始枚举。
反序列化方法应该没有任何问题。