From 45b57c292cd072041e20201992a0d598401d8b23 Mon Sep 17 00:00:00 2001 From: Takatoshi Kondo Date: Thu, 18 Jun 2015 09:59:15 +0900 Subject: [PATCH] Added no default constructible classes support. --- include/msgpack/object.hpp | 17 ++++++ include/msgpack/object_fwd.hpp | 39 ++++++++++++++ test/msgpack_cpp11.cpp | 99 ++++++++++++++++++++++++++++++++++ 3 files changed, 155 insertions(+) diff --git a/include/msgpack/object.hpp b/include/msgpack/object.hpp index fe40f844..8e6ec815 100644 --- a/include/msgpack/object.hpp +++ b/include/msgpack/object.hpp @@ -510,6 +510,8 @@ inline T* object::convert(T* v) const return v; } +#if defined(MSGPACK_USE_CPP03) + template inline T object::as() const { @@ -518,6 +520,21 @@ inline T object::as() const return v; } +#else // defined(MSGPACK_USE_CPP03) + +template +inline typename std::enable_if::value, T>::type object::as() const { + return msgpack::adaptor::as()(*this); +} + +template +inline typename std::enable_if::value, T>::type object::as() const { + T v; + convert(v); + return v; +} + +#endif // defined(MSGPACK_USE_CPP03) inline object::object() { diff --git a/include/msgpack/object_fwd.hpp b/include/msgpack/object_fwd.hpp index ffcc7db5..99e22d0e 100644 --- a/include/msgpack/object_fwd.hpp +++ b/include/msgpack/object_fwd.hpp @@ -81,6 +81,33 @@ struct object_ext { const char* ptr; }; + +#if !defined(MSGPACK_USE_CPP03) +struct object; + +namespace adaptor { +template +struct as; +} // namespace adaptor + +template +struct has_as { +private: + template + static auto check(U*) -> + typename std::is_same< + decltype(msgpack::adaptor::as()(std::declval())), + T>::type; + template + static std::false_type check(...); + using type = decltype(check(nullptr)); +public: + static constexpr bool value = type::value; +}; + +#endif // !defined(MSGPACK_USE_CPP03) + + struct object { union union_type { bool boolean; @@ -102,9 +129,21 @@ struct object { bool is_nil() const { return type == msgpack::type::NIL; } +#if defined(MSGPACK_USE_CPP03) + template T as() const; +#else // defined(MSGPACK_USE_CPP03) + + template + typename std::enable_if::value, T>::type as() const; + + template + typename std::enable_if::value, T>::type as() const; + +#endif // defined(MSGPACK_USE_CPP03) + template T& convert(T& v) const; template diff --git a/test/msgpack_cpp11.cpp b/test/msgpack_cpp11.cpp index 6dd187cb..db3f226f 100644 --- a/test/msgpack_cpp11.cpp +++ b/test/msgpack_cpp11.cpp @@ -185,4 +185,103 @@ TEST(MSGPACK_USER_DEFINED, simple_buffer_enum_class_member) EXPECT_EQ(val1.t3, val2.t3); } +struct no_def_con { + no_def_con() = delete; + no_def_con(int i):i(i) {} + int i; + MSGPACK_DEFINE(i); +}; + +namespace msgpack { +MSGPACK_API_VERSION_NAMESPACE(MSGPACK_DEFAULT_API_NS) { +namespace adaptor { +template <> +struct as { + no_def_con operator()(msgpack::object const& o) const { + if (o.type != msgpack::type::ARRAY) throw msgpack::type_error(); + if (o.via.array.size != 1) throw msgpack::type_error(); + return no_def_con(o.via.array.ptr[0].as()); + } +}; +} // adaptor +} // MSGPACK_API_VERSION_NAMESPACE(MSGPACK_DEFAULT_API_NS) +} // msgpack + +TEST(MSGPACK_NO_DEF_CON, simple_buffer) +{ + no_def_con val1(42); + msgpack::sbuffer sbuf; + msgpack::pack(sbuf, val1); + msgpack::unpacked ret; + msgpack::unpack(ret, sbuf.data(), sbuf.size()); + + no_def_con val2 = ret.get().as(); + EXPECT_EQ(val1.i, val2.i); +} + +struct no_def_con_composite { + no_def_con_composite() = delete; + no_def_con_composite(no_def_con const& a):ndc(a) {} + no_def_con ndc; + MSGPACK_DEFINE(ndc); +}; + +namespace msgpack { +MSGPACK_API_VERSION_NAMESPACE(MSGPACK_DEFAULT_API_NS) { +namespace adaptor { +template <> +struct as { + no_def_con_composite operator()(msgpack::object const& o) const { + if (o.type != msgpack::type::ARRAY) throw msgpack::type_error(); + if (o.via.array.size != 1) throw msgpack::type_error(); + return no_def_con_composite(o.via.array.ptr[0].as()); + } +}; +} // adaptor +} // MSGPACK_API_VERSION_NAMESPACE(MSGPACK_DEFAULT_API_NS) +} // msgpack + +TEST(MSGPACK_NO_DEF_CON_COMPOSITE, simple_buffer) +{ + no_def_con_composite val1(42); + msgpack::sbuffer sbuf; + msgpack::pack(sbuf, val1); + msgpack::unpacked ret; + msgpack::unpack(ret, sbuf.data(), sbuf.size()); + no_def_con_composite val2 = ret.get().as(); + EXPECT_EQ(val1.ndc.i, val2.ndc.i); +} + +struct no_def_con_inherit : no_def_con { + no_def_con_inherit() = delete; + no_def_con_inherit(no_def_con const& a):no_def_con(a) {} + MSGPACK_DEFINE(MSGPACK_BASE(no_def_con)); +}; + +namespace msgpack { +MSGPACK_API_VERSION_NAMESPACE(MSGPACK_DEFAULT_API_NS) { +namespace adaptor { +template <> +struct as { + no_def_con_inherit operator()(msgpack::object const& o) const { + if (o.type != msgpack::type::ARRAY) throw msgpack::type_error(); + if (o.via.array.size != 1) throw msgpack::type_error(); + return no_def_con_inherit(o.via.array.ptr[0].as()); + } +}; +} // adaptor +} // MSGPACK_API_VERSION_NAMESPACE(MSGPACK_DEFAULT_API_NS) +} // msgpack + +TEST(MSGPACK_NO_DEF_CON_INHERIT, simple_buffer) +{ + no_def_con_inherit val1(42); + msgpack::sbuffer sbuf; + msgpack::pack(sbuf, val1); + msgpack::unpacked ret; + msgpack::unpack(ret, sbuf.data(), sbuf.size()); + no_def_con_inherit val2 = ret.get().as(); + EXPECT_EQ(val1.i, val2.i); +} + #endif // !defined(MSGPACK_USE_CPP03)