1// 2// MessagePack for C++ static resolution routine 3// 4// Copyright (C) 2008-2015 FURUHASHI Sadayuki and KONDO Takatoshi 5// 6// Distributed under the Boost Software License, Version 1.0. 7// (See accompanying file LICENSE_1_0.txt or copy at 8// http://www.boost.org/LICENSE_1_0.txt) 9// 10#ifndef MSGPACK_CPP11_MSGPACK_TUPLE_HPP 11#define MSGPACK_CPP11_MSGPACK_TUPLE_HPP 12 13#include "msgpack/versioning.hpp" 14#include "msgpack/object_fwd.hpp" 15#include "msgpack/meta.hpp" 16 17#include <tuple> 18 19namespace msgpack { 20 21/// @cond 22MSGPACK_API_VERSION_NAMESPACE(v1) { 23/// @endcond 24 25namespace type { 26 // tuple 27 using std::get; 28 using std::tuple_size; 29 using std::tuple_element; 30 using std::uses_allocator; 31 using std::ignore; 32 using std::swap; 33 34 template< class... Types > 35 class tuple : public std::tuple<Types...> { 36 public: 37 using base = std::tuple<Types...>; 38 39 40 tuple(tuple const&) = default; 41 tuple(tuple&&) = default; 42 43 template<typename... OtherTypes> 44 tuple(OtherTypes&&... other):base(std::forward<OtherTypes>(other)...) {} 45 46 template<typename... OtherTypes> 47 tuple(tuple<OtherTypes...> const& other):base(static_cast<std::tuple<OtherTypes...> const&>(other)) {} 48 template<typename... OtherTypes> 49 tuple(tuple<OtherTypes...> && other):base(static_cast<std::tuple<OtherTypes...> &&>(other)) {} 50 51 tuple& operator=(tuple const&) = default; 52 tuple& operator=(tuple&&) = default; 53 54 template<typename... OtherTypes> 55 tuple& operator=(tuple<OtherTypes...> const& other) { 56 *static_cast<base*>(this) = static_cast<std::tuple<OtherTypes...> const&>(other); 57 return *this; 58 } 59 template<typename... OtherTypes> 60 tuple& operator=(tuple<OtherTypes...> && other) { 61 *static_cast<base*>(this) = static_cast<std::tuple<OtherTypes...> &&>(other); 62 return *this; 63 } 64 65 template< std::size_t I> 66 typename tuple_element<I, base >::type& 67 get() & { return std::get<I>(*this); } 68 69 template< std::size_t I> 70 typename tuple_element<I, base >::type const& 71 get() const& { return std::get<I>(*this); } 72 73 template< std::size_t I> 74 typename tuple_element<I, base >::type&& 75 get() && { return std::get<I>(*this); } 76 }; 77 78 template <class... Args> 79 inline tuple<Args...> make_tuple(Args&&... args) { 80 return tuple<Args...>(args...); 81 } 82 83 template<class... Args> 84 inline tuple<Args&&...> forward_as_tuple (Args&&... args) noexcept { 85 return tuple<Args&&...>(std::forward<Args>(args)...); 86 } 87 88 template <class... Tuples> 89 inline auto tuple_cat(Tuples&&... args) -> 90 decltype( 91 std::tuple_cat(std::forward<typename std::remove_reference<Tuples>::type::base>(args)...) 92 ) { 93 return std::tuple_cat(std::forward<typename std::remove_reference<Tuples>::type::base>(args)...); 94 } 95 template <class... Args> 96 inline tuple<Args&...> tie(Args&... args) { 97 return tuple<Args&...>(args...); 98 } 99} // namespace type 100 101// --- Pack from tuple to packer stream --- 102template <typename Stream, typename Tuple, std::size_t N> 103struct MsgpackTuplePacker { 104 static void pack( 105 msgpack::packer<Stream>& o, 106 const Tuple& v) { 107 MsgpackTuplePacker<Stream, Tuple, N-1>::pack(o, v); 108 o.pack(type::get<N-1>(v)); 109 } 110}; 111 112template <typename Stream, typename Tuple> 113struct MsgpackTuplePacker<Stream, Tuple, 1> { 114 static void pack ( 115 msgpack::packer<Stream>& o, 116 const Tuple& v) { 117 o.pack(type::get<0>(v)); 118 } 119}; 120 121template <typename Stream, typename Tuple> 122struct MsgpackTuplePacker<Stream, Tuple, 0> { 123 static void pack ( 124 msgpack::packer<Stream>&, 125 const Tuple&) { 126 } 127}; 128 129namespace adaptor { 130 131template <typename... Args> 132struct pack<msgpack::type::tuple<Args...>> { 133 template <typename Stream> 134 msgpack::packer<Stream>& operator()( 135 msgpack::packer<Stream>& o, 136 const msgpack::type::tuple<Args...>& v) const { 137 o.pack_array(sizeof...(Args)); 138 MsgpackTuplePacker<Stream, decltype(v), sizeof...(Args)>::pack(o, v); 139 return o; 140 } 141}; 142 143} // namespace adaptor 144 145// --- Convert from tuple to object --- 146 147template <typename... Args> 148struct MsgpackTupleAs; 149 150template <typename T, typename... Args> 151struct MsgpackTupleAsImpl { 152 static msgpack::type::tuple<T, Args...> as(msgpack::object const& o) { 153 return msgpack::type::tuple_cat( 154 msgpack::type::make_tuple(o.via.array.ptr[o.via.array.size - sizeof...(Args) - 1].as<T>()), 155 MsgpackTupleAs<Args...>::as(o)); 156 } 157}; 158 159template <typename... Args> 160struct MsgpackTupleAs { 161 static msgpack::type::tuple<Args...> as(msgpack::object const& o) { 162 return MsgpackTupleAsImpl<Args...>::as(o); 163 } 164}; 165 166template <> 167struct MsgpackTupleAs<> { 168 static msgpack::type::tuple<> as (msgpack::object const&) { 169 return msgpack::type::tuple<>(); 170 } 171}; 172 173template <typename Tuple, std::size_t N> 174struct MsgpackTupleConverter { 175 static void convert( 176 msgpack::object const& o, 177 Tuple& v) { 178 MsgpackTupleConverter<Tuple, N-1>::convert(o, v); 179 o.via.array.ptr[N-1].convert<typename std::remove_reference<decltype(type::get<N-1>(v))>::type>(type::get<N-1>(v)); 180 } 181}; 182 183template <typename Tuple> 184struct MsgpackTupleConverter<Tuple, 1> { 185 static void convert ( 186 msgpack::object const& o, 187 Tuple& v) { 188 o.via.array.ptr[0].convert<typename std::remove_reference<decltype(type::get<0>(v))>::type>(type::get<0>(v)); 189 } 190}; 191 192template <typename Tuple> 193struct MsgpackTupleConverter<Tuple, 0> { 194 static void convert ( 195 msgpack::object const&, 196 Tuple&) { 197 } 198}; 199 200namespace adaptor { 201 202template <typename... Args> 203struct as<msgpack::type::tuple<Args...>, typename std::enable_if<msgpack::all_of<msgpack::has_as, Args...>::value>::type> { 204 msgpack::type::tuple<Args...> operator()( 205 msgpack::object const& o) const { 206 if (o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); } 207 if (o.via.array.size < sizeof...(Args)) { throw msgpack::type_error(); } 208 return MsgpackTupleAs<Args...>::as(o); 209 } 210}; 211 212template <typename... Args> 213struct convert<msgpack::type::tuple<Args...>> { 214 msgpack::object const& operator()( 215 msgpack::object const& o, 216 msgpack::type::tuple<Args...>& v) const { 217 if(o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); } 218 if(o.via.array.size < sizeof...(Args)) { throw msgpack::type_error(); } 219 MsgpackTupleConverter<decltype(v), sizeof...(Args)>::convert(o, v); 220 return o; 221 } 222}; 223 224} // namespace adaptor 225 226// --- Convert from tuple to object with zone --- 227template <typename Tuple, std::size_t N> 228struct MsgpackTupleToObjectWithZone { 229 static void convert( 230 msgpack::object::with_zone& o, 231 const Tuple& v) { 232 MsgpackTupleToObjectWithZone<Tuple, N-1>::convert(o, v); 233 o.via.array.ptr[N-1] = msgpack::object(type::get<N-1>(v), o.zone); 234 } 235}; 236 237template <typename Tuple> 238struct MsgpackTupleToObjectWithZone<Tuple, 1> { 239 static void convert ( 240 msgpack::object::with_zone& o, 241 const Tuple& v) { 242 o.via.array.ptr[0] = msgpack::object(type::get<0>(v), o.zone); 243 } 244}; 245 246template <typename Tuple> 247struct MsgpackTupleToObjectWithZone<Tuple, 0> { 248 static void convert ( 249 msgpack::object::with_zone&, 250 const Tuple&) { 251 } 252}; 253 254namespace adaptor { 255 256template <typename... Args> 257 struct object_with_zone<msgpack::type::tuple<Args...>> { 258 void operator()( 259 msgpack::object::with_zone& o, 260 msgpack::type::tuple<Args...> const& v) const { 261 o.type = msgpack::type::ARRAY; 262 o.via.array.ptr = static_cast<msgpack::object*>(o.zone.allocate_align(sizeof(msgpack::object)*sizeof...(Args))); 263 o.via.array.size = sizeof...(Args); 264 MsgpackTupleToObjectWithZone<decltype(v), sizeof...(Args)>::convert(o, v); 265 } 266}; 267 268} // namespace adaptor 269 270/// @cond 271} // MSGPACK_API_VERSION_NAMESPACE(v1) 272///@endcond 273 274} // namespace msgpack 275 276#endif // MSGPACK_CPP11_MSGPACK_TUPLE_HPP 277