Следующий образец не компилируется, жалуясь, что
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
и соответствующая ошибка для другого класса enum. Мой вопрос заключается в том, как с помощью API-интерфейса c ++ msgpack можно сериализовать класс с членами класса 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 ++.
Вы можете использовать макрос 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());
}
Один способ, который, кажется, работает, состоит в том, чтобы обернуть перечисление в союз …
union log_level_t {
log_level lev;
int levint;
}
...
log_level_t lev_;
...
MSGPACK_DEFINE(lev_.levint, dom_.domint, msg);
Это похоже на дерьмовый подход, но он работает.
Я нашел другое решение, возможно, немного более элегантное (хорошо, оно не так идеально):
MSGPACK_DEFINE((int&)lev_, (int&)dom_, msg)
Таким образом, вы можете сохранить свое первоначальное перечисление, не создавая новый союз.
Метод десериализации должен работать без проблем.