Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions include/msgpack/object.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,8 @@ inline T* object::convert(T* v) const
return v;
}

#if defined(MSGPACK_USE_CPP03)

template <typename T>
inline T object::as() const
{
Expand All @@ -518,6 +520,21 @@ inline T object::as() const
return v;
}

#else // defined(MSGPACK_USE_CPP03)

template <typename T>
inline typename std::enable_if<msgpack::has_as<T>::value, T>::type object::as() const {
return msgpack::adaptor::as<T>()(*this);
}

template <typename T>
inline typename std::enable_if<!msgpack::has_as<T>::value, T>::type object::as() const {
T v;
convert(v);
return v;
}

#endif // defined(MSGPACK_USE_CPP03)

inline object::object()
{
Expand Down
39 changes: 39 additions & 0 deletions include/msgpack/object_fwd.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,33 @@ struct object_ext {
const char* ptr;
};


#if !defined(MSGPACK_USE_CPP03)
struct object;

namespace adaptor {
template <typename T>
struct as;
} // namespace adaptor

template <typename T>
struct has_as {
private:
template <typename U>
static auto check(U*) ->
typename std::is_same<
decltype(msgpack::adaptor::as<U>()(std::declval<msgpack::object>())),
T>::type;
template <typename>
static std::false_type check(...);
using type = decltype(check<T>(nullptr));
public:
static constexpr bool value = type::value;
};

#endif // !defined(MSGPACK_USE_CPP03)


struct object {
union union_type {
bool boolean;
Expand All @@ -102,9 +129,21 @@ struct object {

bool is_nil() const { return type == msgpack::type::NIL; }

#if defined(MSGPACK_USE_CPP03)

template <typename T>
T as() const;

#else // defined(MSGPACK_USE_CPP03)

template <typename T>
typename std::enable_if<msgpack::has_as<T>::value, T>::type as() const;

template <typename T>
typename std::enable_if<!msgpack::has_as<T>::value, T>::type as() const;

#endif // defined(MSGPACK_USE_CPP03)

template <typename T>
T& convert(T& v) const;
template <typename T>
Expand Down
99 changes: 99 additions & 0 deletions test/msgpack_cpp11.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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> {
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<int>());
}
};
} // 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<no_def_con>();
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> {
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<no_def_con>());
}
};
} // 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<no_def_con_composite>();
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> {
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<no_def_con>());
}
};
} // 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<no_def_con_inherit>();
EXPECT_EQ(val1.i, val2.i);
}

#endif // !defined(MSGPACK_USE_CPP03)