Skip to content

Commit

Permalink
Merge pull request #302 from redboltz/add_no_defcon_support
Browse files Browse the repository at this point in the history
Added no default constructible classes support.
  • Loading branch information
redboltz committed Jul 5, 2015
2 parents 9e7564c + 45b57c2 commit b559187
Show file tree
Hide file tree
Showing 3 changed files with 155 additions and 0 deletions.
17 changes: 17 additions & 0 deletions include/msgpack/object.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -511,6 +511,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 @@ -519,6 +521,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)

0 comments on commit b559187

Please sign in to comment.