Skip to content

Commit 2a7d997

Browse files
committed
Merge pull request #327 from redboltz/jonitis-vector_of_non_default_constructible_values_2
Add 'as' support for containers.
2 parents 1b13523 + a746afa commit 2a7d997

File tree

18 files changed

+696
-82
lines changed

18 files changed

+696
-82
lines changed

CMakeLists.txt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ IF (MSGPACK_ENABLE_CXX)
146146
include/msgpack/detail/cpp03_zone.hpp
147147
include/msgpack/detail/cpp11_zone.hpp
148148
include/msgpack/fbuffer.hpp
149+
include/msgpack/meta.hpp
149150
include/msgpack/object.hpp
150151
include/msgpack/object_fwd.hpp
151152
include/msgpack/pack.hpp
@@ -201,8 +202,8 @@ IF (MSGPACK_BUILD_TESTS)
201202
ENDIF ()
202203

203204
IF ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
204-
SET_PROPERTY (TARGET msgpack APPEND_STRING PROPERTY COMPILE_FLAGS "-Wall -Wextra -Werror -g -O3 -DPIC")
205-
SET_PROPERTY (TARGET msgpack-static APPEND_STRING PROPERTY COMPILE_FLAGS "-Wall -Wextra -Werror -g -O3" )
205+
SET_PROPERTY (TARGET msgpack APPEND_STRING PROPERTY COMPILE_FLAGS "-Wall -Wextra -Wno-mismatched-tags -Werror -g -O3 -DPIC")
206+
SET_PROPERTY (TARGET msgpack-static APPEND_STRING PROPERTY COMPILE_FLAGS "-Wall -Wextra -Wno-mismatched-tags -Werror -g -O3" )
206207
ENDIF ()
207208
IF ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
208209
IF (CMAKE_CXX_FLAGS MATCHES "/W[0-4]")

configure.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ AC_SUBST(CFLAGS)
66
CFLAGS="-O3 -Wall -Wextra -Werror $CFLAGS"
77

88
AC_SUBST(CXXFLAGS)
9-
CXXFLAGS="-O3 -Wall -Wextra -Werror $CXXFLAGS"
9+
CXXFLAGS="-O3 -Wall -Wextra -Wno-mismatched-tags -Werror $CXXFLAGS"
1010

1111

1212
AC_PROG_CC

include/msgpack/adaptor/cpp11/array.hpp

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,56 @@ MSGPACK_API_VERSION_NAMESPACE(v1) {
3333

3434
namespace adaptor {
3535

36+
namespace detail {
37+
38+
template<std::size_t... Is> struct seq {};
39+
40+
template<std::size_t N, std::size_t... Is>
41+
struct gen_seq : gen_seq<N-1, N-1, Is...> {};
42+
43+
template<std::size_t... Is>
44+
struct gen_seq<0, Is...> : seq<Is...> {};
45+
46+
template<typename T, std::size_t N1, std::size_t... I1, std::size_t N2, std::size_t... I2>
47+
inline std::array<T, N1+N2> concat(
48+
std::array<T, N1>&& a1,
49+
std::array<T, N2>&& a2,
50+
seq<I1...>,
51+
seq<I2...>) {
52+
return {{ std::move(a1[I1])..., std::move(a2[I2])... }};
53+
}
54+
55+
template<typename T, std::size_t N1, std::size_t N2>
56+
inline std::array<T, N1+N2> concat(std::array<T, N1>&& a1, std::array<T, N2>&& a2) {
57+
return concat(std::move(a1), std::move(a2), gen_seq<N1>(), gen_seq<N2>());
58+
}
59+
60+
template <typename T, std::size_t N>
61+
struct as_impl {
62+
static std::array<T, N> as(msgpack::object const& o) {
63+
msgpack::object* p = o.via.array.ptr + N - 1;
64+
return concat(as_impl<T, N-1>::as(o), std::array<T, 1>{{p->as<T>()}});
65+
}
66+
};
67+
68+
template <typename T>
69+
struct as_impl<T, 0> {
70+
static std::array<T, 0> as(msgpack::object const&) {
71+
return std::array<T, 0>();
72+
}
73+
};
74+
75+
} // namespace detail
76+
77+
template <typename T, std::size_t N>
78+
struct as<std::array<T, N>, typename std::enable_if<msgpack::has_as<T>::value>::type> {
79+
std::array<T, N> operator()(msgpack::object const& o) const {
80+
if(o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); }
81+
if(o.via.array.size != N) { throw msgpack::type_error(); }
82+
return detail::as_impl<T, N>::as(o);
83+
}
84+
};
85+
3686
template <typename T, std::size_t N>
3787
struct convert<std::array<T, N>> {
3888
msgpack::object const& operator()(msgpack::object const& o, std::array<T, N>& v) const {

include/msgpack/adaptor/cpp11/forward_list.hpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,21 @@ MSGPACK_API_VERSION_NAMESPACE(v1) {
3333

3434
namespace adaptor {
3535

36+
template <typename T>
37+
struct as<std::forward_list<T>, typename std::enable_if<msgpack::has_as<T>::value>::type> {
38+
std::forward_list<T> operator()(msgpack::object const& o) const {
39+
if (o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); }
40+
std::forward_list<T> v;
41+
msgpack::object* p = o.via.array.ptr + o.via.array.size;
42+
msgpack::object* const pend = o.via.array.ptr;
43+
while (p != pend) {
44+
--p;
45+
v.push_front(p->as<T>());
46+
}
47+
return v;
48+
}
49+
};
50+
3651
template <typename T>
3752
struct convert<std::forward_list<T>> {
3853
msgpack::object const& operator()(msgpack::object const& o, std::forward_list<T>& v) const {

include/msgpack/adaptor/cpp11/tuple.hpp

Lines changed: 37 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "msgpack/versioning.hpp"
2222
#include "msgpack/adaptor/adaptor_base.hpp"
2323
#include "msgpack/adaptor/check_container_size.hpp"
24+
#include "msgpack/meta.hpp"
2425

2526
#include <tuple>
2627

@@ -41,15 +42,6 @@ struct StdTuplePacker {
4142
}
4243
};
4344

44-
template <typename Stream, typename Tuple>
45-
struct StdTuplePacker<Stream, Tuple, 1> {
46-
static void pack (
47-
msgpack::packer<Stream>& o,
48-
const Tuple& v) {
49-
o.pack(std::get<0>(v));
50-
}
51-
};
52-
5345
template <typename Stream, typename Tuple>
5446
struct StdTuplePacker<Stream, Tuple, 0> {
5547
static void pack (
@@ -77,6 +69,32 @@ struct pack<std::tuple<Args...>> {
7769

7870
// --- Convert from tuple to object ---
7971

72+
template <typename... Args>
73+
struct StdTupleAs;
74+
75+
template <typename T, typename... Args>
76+
struct StdTupleAsImpl {
77+
static std::tuple<T, Args...> as(msgpack::object const& o) {
78+
return std::tuple_cat(
79+
std::make_tuple(o.via.array.ptr[o.via.array.size - sizeof...(Args) - 1].as<T>()),
80+
StdTupleAs<Args...>::as(o));
81+
}
82+
};
83+
84+
template <typename... Args>
85+
struct StdTupleAs {
86+
static std::tuple<Args...> as(msgpack::object const& o) {
87+
return StdTupleAsImpl<Args...>::as(o);
88+
}
89+
};
90+
91+
template <>
92+
struct StdTupleAs<> {
93+
static std::tuple<> as (msgpack::object const&) {
94+
return std::tuple<>();
95+
}
96+
};
97+
8098
template <typename Tuple, std::size_t N>
8199
struct StdTupleConverter {
82100
static void convert(
@@ -87,15 +105,6 @@ struct StdTupleConverter {
87105
}
88106
};
89107

90-
template <typename Tuple>
91-
struct StdTupleConverter<Tuple, 1> {
92-
static void convert (
93-
msgpack::object const& o,
94-
Tuple& v) {
95-
o.via.array.ptr[0].convert<typename std::remove_reference<decltype(std::get<0>(v))>::type>(std::get<0>(v));
96-
}
97-
};
98-
99108
template <typename Tuple>
100109
struct StdTupleConverter<Tuple, 0> {
101110
static void convert (
@@ -106,6 +115,16 @@ struct StdTupleConverter<Tuple, 0> {
106115

107116
namespace adaptor {
108117

118+
template <typename... Args>
119+
struct as<std::tuple<Args...>, typename std::enable_if<msgpack::all_of<msgpack::has_as, Args...>::value>::type> {
120+
std::tuple<Args...> operator()(
121+
msgpack::object const& o) const {
122+
if (o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); }
123+
if (o.via.array.size < sizeof...(Args)) { throw msgpack::type_error(); }
124+
return StdTupleAs<Args...>::as(o);
125+
}
126+
};
127+
109128
template <typename... Args>
110129
struct convert<std::tuple<Args...>> {
111130
msgpack::object const& operator()(
@@ -131,15 +150,6 @@ struct StdTupleToObjectWithZone {
131150
}
132151
};
133152

134-
template <typename Tuple>
135-
struct StdTupleToObjectWithZone<Tuple, 1> {
136-
static void convert (
137-
msgpack::object::with_zone& o,
138-
const Tuple& v) {
139-
o.via.array.ptr[0] = msgpack::object(std::get<0>(v), o.zone);
140-
}
141-
};
142-
143153
template <typename Tuple>
144154
struct StdTupleToObjectWithZone<Tuple, 0> {
145155
static void convert (

include/msgpack/adaptor/cpp11/unordered_map.hpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,22 @@ MSGPACK_API_VERSION_NAMESPACE(v1) {
3232

3333
namespace adaptor {
3434

35+
template <typename K, typename V>
36+
struct as<
37+
std::unordered_map<K, V>,
38+
typename std::enable_if<msgpack::has_as<K>::value && msgpack::has_as<V>::value>::type> {
39+
std::unordered_map<K, V> operator()(msgpack::object const& o) const {
40+
if (o.type != msgpack::type::MAP) { throw msgpack::type_error(); }
41+
msgpack::object_kv* p(o.via.map.ptr);
42+
msgpack::object_kv* const pend(o.via.map.ptr + o.via.map.size);
43+
std::unordered_map<K, V> v;
44+
for (; p != pend; ++p) {
45+
v.emplace(p->key.as<K>(), p->val.as<V>());
46+
}
47+
return v;
48+
}
49+
};
50+
3551
template <typename K, typename V>
3652
struct convert<std::unordered_map<K, V>> {
3753
msgpack::object const& operator()(msgpack::object const& o, std::unordered_map<K, V>& v) const {
@@ -89,6 +105,22 @@ struct object_with_zone<std::unordered_map<K, V>> {
89105
};
90106

91107

108+
template <typename K, typename V>
109+
struct as<
110+
std::unordered_multimap<K, V>,
111+
typename std::enable_if<msgpack::has_as<K>::value && msgpack::has_as<V>::value>::type> {
112+
std::unordered_multimap<K, V> operator()(msgpack::object const& o) const {
113+
if (o.type != msgpack::type::MAP) { throw msgpack::type_error(); }
114+
msgpack::object_kv* p(o.via.map.ptr);
115+
msgpack::object_kv* const pend(o.via.map.ptr + o.via.map.size);
116+
std::unordered_multimap<K, V> v;
117+
for (; p != pend; ++p) {
118+
v.emplace(p->key.as<K>(), p->val.as<V>());
119+
}
120+
return v;
121+
}
122+
};
123+
92124
template <typename K, typename V>
93125
struct convert<std::unordered_multimap<K, V>> {
94126
msgpack::object const& operator()(msgpack::object const& o, std::unordered_multimap<K, V>& v) const {

include/msgpack/adaptor/cpp11/unordered_set.hpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,21 @@ MSGPACK_API_VERSION_NAMESPACE(v1) {
3232

3333
namespace adaptor {
3434

35+
template <typename T>
36+
struct as<std::unordered_set<T>, typename std::enable_if<msgpack::has_as<T>::value>::type> {
37+
std::unordered_set<T> operator()(msgpack::object const& o) const {
38+
if (o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); }
39+
msgpack::object* p = o.via.array.ptr + o.via.array.size;
40+
msgpack::object* const pbegin = o.via.array.ptr;
41+
std::unordered_set<T> v;
42+
while (p > pbegin) {
43+
--p;
44+
v.insert(p->as<T>());
45+
}
46+
return v;
47+
}
48+
};
49+
3550
template <typename T>
3651
struct convert<std::unordered_set<T>> {
3752
msgpack::object const& operator()(msgpack::object const& o, std::unordered_set<T>& v) const {
@@ -86,6 +101,21 @@ struct object_with_zone<std::unordered_set<T>> {
86101
};
87102

88103

104+
template <typename T>
105+
struct as<std::unordered_multiset<T>, typename std::enable_if<msgpack::has_as<T>::value>::type> {
106+
std::unordered_multiset<T> operator()(msgpack::object const& o) const {
107+
if (o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); }
108+
msgpack::object* p = o.via.array.ptr + o.via.array.size;
109+
msgpack::object* const pbegin = o.via.array.ptr;
110+
std::unordered_multiset<T> v;
111+
while (p > pbegin) {
112+
--p;
113+
v.insert(p->as<T>());
114+
}
115+
return v;
116+
}
117+
};
118+
89119
template <typename T>
90120
struct convert<std::unordered_multiset<T>> {
91121
msgpack::object const& operator()(msgpack::object const& o, std::unordered_multiset<T>& v) const {

0 commit comments

Comments
 (0)