CppWAMP
C++11 client library for the WAMP protocol
tuple.hpp
Go to the documentation of this file.
1 /*------------------------------------------------------------------------------
2  Copyright Butterfly Energy Systems 2014-2015, 2022.
3  Distributed under the Boost Software License, Version 1.0.
4  http://www.boost.org/LICENSE_1_0.txt
5 ------------------------------------------------------------------------------*/
6 
7 #ifndef CPPWAMP_TYPES_TUPLE_HPP
8 #define CPPWAMP_TYPES_TUPLE_HPP
9 
10 //------------------------------------------------------------------------------
14 //------------------------------------------------------------------------------
15 
16 #include <sstream>
17 #include <type_traits>
18 #include "../api.hpp"
19 #include "../variant.hpp"
20 #include "../internal/integersequence.hpp"
21 
22 namespace wamp
23 {
24 
25 //------------------------------------------------------------------------------
31 //------------------------------------------------------------------------------
32 template <typename... Ts>
33 CPPWAMP_API void toTuple(const wamp::Variant::Array& array,
34  std::tuple<Ts...>& tuple);
35 
36 //------------------------------------------------------------------------------
40 //------------------------------------------------------------------------------
41 template <typename... Ts>
42 CPPWAMP_API wamp::Variant::Array toArray(const std::tuple<Ts...>& tuple);
43 
44 //------------------------------------------------------------------------------
47 //------------------------------------------------------------------------------
48 template <typename... Ts>
49 CPPWAMP_API void convert(FromVariantConverter& conv, std::tuple<Ts...>& tuple);
50 
51 //------------------------------------------------------------------------------
54 //------------------------------------------------------------------------------
55 template <typename... Ts>
56 CPPWAMP_API void convert(ToVariantConverter& conv, std::tuple<Ts...>& tuple);
57 
58 //------------------------------------------------------------------------------
60 //------------------------------------------------------------------------------
61 template <typename... Ts>
62 CPPWAMP_API bool operator==(const Array& array, const std::tuple<Ts...>& tuple);
63 
64 //------------------------------------------------------------------------------
66 //------------------------------------------------------------------------------
67 template <typename... Ts>
68 CPPWAMP_API bool operator==(const std::tuple<Ts...>& tuple, const Array& array);
69 
70 //------------------------------------------------------------------------------
72 //------------------------------------------------------------------------------
73 template <typename... Ts>
74 CPPWAMP_API bool operator!=(const Array& array, const std::tuple<Ts...>& tuple);
75 
76 //------------------------------------------------------------------------------
78 //------------------------------------------------------------------------------
79 template <typename... Ts>
80 CPPWAMP_API bool operator!=(const std::tuple<Ts...>& tuple, const Array& array);
81 
82 //------------------------------------------------------------------------------
84 //------------------------------------------------------------------------------
85 template <typename... Ts>
86 CPPWAMP_API bool operator==(const Variant& variant,
87  const std::tuple<Ts...>& tuple);
88 
89 //------------------------------------------------------------------------------
91 //------------------------------------------------------------------------------
92 template <typename... Ts>
93 CPPWAMP_API bool operator==(const std::tuple<Ts...>& tuple,
94  const Variant& variant);
95 
96 //------------------------------------------------------------------------------
98 //------------------------------------------------------------------------------
99 template <typename... Ts>
100 CPPWAMP_API bool operator!=(const Variant& variant,
101  const std::tuple<Ts...>& tuple);
102 
103 //------------------------------------------------------------------------------
105 //------------------------------------------------------------------------------
106 template <typename... Ts>
107 CPPWAMP_API bool operator!=(const std::tuple<Ts...>& tuple,
108  const Variant& variant);
109 
110 
111 //******************************************************************************
112 // Internal helper types and functions
113 //******************************************************************************
114 
115 namespace internal
116 {
117 
118 //------------------------------------------------------------------------------
119 template <int N, typename...Ts>
120 int toTupleElement(const Array& array, std::tuple<Ts...>& tuple)
121 {
122  auto& elem = std::get<N>(tuple);
123  try
124  {
125  array.at(N).to(elem);
126  }
127  catch (const error::Conversion& e)
128  {
129  std::ostringstream oss;
130  oss << e.what() << " (for tuple element #" << N << ")";
131  throw error::Conversion(oss.str());
132  }
133  return 0;
134 }
135 
136 template <int N, typename...Ts>
137 int fromTupleElement(Array& array, const std::tuple<Ts...>& tuple)
138 {
139  const auto& elem = std::get<N>(tuple);
140  array.emplace_back(Variant::from(elem));
141  return 0;
142 }
143 
144 template <typename... Ts, int ...Seq>
145 void convertToTuple(const Array& array, std::tuple<Ts...>& tuple,
146  internal::IntegerSequence<Seq...>)
147 {
148  if (array.size() != sizeof...(Ts))
149  throw error::Conversion("Cannot convert variant array to tuple; "
150  "sizes do not match");
151  using swallow = int[]; // Guarantees left-to-right evaluation
152  (void)swallow{0, toTupleElement<Seq>(array, tuple)...};
153 }
154 
155 template <typename... Ts, int ...Seq>
156 void convertFromTuple(Array& array, const std::tuple<Ts...>& tuple,
157  internal::IntegerSequence<Seq...>)
158 {
159  array.reserve(sizeof...(Ts));
160  using swallow = int[]; // Guarantees left-to-right evaluation
161  (void)swallow{0, fromTupleElement<Seq>(array, tuple)...};
162 }
163 
164 //------------------------------------------------------------------------------
165 template <std::size_t N, typename... Ts>
166 using EnableIfTupleElement = EnableIf<N != sizeof...(Ts)>;
167 
168 template <std::size_t N, typename... Ts>
169 using EnableIfTupleEnd = EnableIf<N == sizeof...(Ts)>;
170 
171 template <std::size_t N = 0, typename... Ts, EnableIfTupleEnd<N, Ts...> = 0>
172 bool equalsTuple(const Array&, const std::tuple<Ts...>&)
173 {
174  return true;
175 }
176 
177 template <std::size_t N = 0, typename... Ts, EnableIfTupleElement<N, Ts...> = 0>
178 bool equalsTuple(const Array& array, const std::tuple<Ts...>& tuple)
179 {
180  const auto& arrayElem = array.at(N);
181  const auto& tupleElem = std::get<N>(tuple);
182  bool result = (arrayElem == tupleElem);
183  return result && equalsTuple<N+1, Ts...>(array, tuple);
184 }
185 
186 //------------------------------------------------------------------------------
187 template <std::size_t N = 0, typename... Ts, EnableIfTupleEnd<N, Ts...> = 0>
188 bool notEqualsTuple(const Array&, const std::tuple<Ts...>&)
189 {
190  return false;
191 }
192 
193 template <std::size_t N = 0, typename... Ts, EnableIfTupleElement<N, Ts...> = 0>
194 bool notEqualsTuple(const Array& array, const std::tuple<Ts...>& tuple)
195 {
196  const auto& arrayElem = array.at(N);
197  const auto& tupleElem = std::get<N>(tuple);
198  bool result = (arrayElem != tupleElem);
199  return result || notEqualsTuple<N+1, Ts...>(array, tuple);
200 }
201 
202 } // namespace internal
203 
204 
205 //******************************************************************************
206 // Tuple conversion function implementations
207 //******************************************************************************
208 
209 //------------------------------------------------------------------------------
210 template <typename... Ts>
211 void toTuple(const wamp::Variant::Array& array, std::tuple<Ts...>& tuple)
212 {
213  using Seq = typename internal::GenIntegerSequence<sizeof...(Ts)>::type;
214  convertToTuple(array, tuple, Seq());
215 }
216 
217 //------------------------------------------------------------------------------
218 template <typename... Ts>
219 wamp::Variant::Array toArray(const std::tuple<Ts...>& tuple)
220 {
221  using Seq = typename internal::GenIntegerSequence<sizeof...(Ts)>::type;
222  Array array;
223  convertFromTuple(array, tuple, Seq());
224  return array;
225 }
226 
227 //------------------------------------------------------------------------------
228 template <typename... Ts>
229 void convert(FromVariantConverter& conv, std::tuple<Ts...>& tuple)
230 {
231  auto& variant = conv.variant();
232  if (!variant.is<Array>())
233  {
234  throw error::Conversion("Cannot convert variant to tuple; "
235  "the variant is not an array");
236  }
237  toTuple(variant.as<Array>(), tuple);
238 }
239 
240 //------------------------------------------------------------------------------
241 template <typename... Ts>
242 void convert(ToVariantConverter& conv, std::tuple<Ts...>& tuple)
243 {
244  conv.variant() = toArray(tuple);
245 }
246 
247 //------------------------------------------------------------------------------
248 template <typename... Ts>
249 bool operator==(const Array& array, const std::tuple<Ts...>& tuple)
250 {
251  auto N = std::tuple_size<std::tuple<Ts...>>::value;
252  return array.size() == N ? internal::equalsTuple(array, tuple) : false;
253 }
254 
255 //------------------------------------------------------------------------------
256 template <typename... Ts>
257 bool operator==(const std::tuple<Ts...>& tuple, const Array& array)
258 {
259  return array == tuple;
260 }
261 
262 //------------------------------------------------------------------------------
263 template <typename... Ts>
264 bool operator!=(const Array& array, const std::tuple<Ts...>& tuple)
265 {
266  auto N = std::tuple_size<std::tuple<Ts...>>::value;
267  return array.size() == N ? internal::notEqualsTuple(array, tuple) : true;
268 }
269 
270 //------------------------------------------------------------------------------
271 template <typename... Ts>
272 bool operator!=(const std::tuple<Ts...>& tuple, const Array& array)
273 {
274  return array != tuple;
275 }
276 
277 //------------------------------------------------------------------------------
278 template <typename... Ts>
279 bool operator==(const Variant& variant, const std::tuple<Ts...>& tuple)
280 {
281  return variant.is<Array>() && variant.as<Array>() == tuple;
282 }
283 
284 //------------------------------------------------------------------------------
285 template <typename... Ts>
286 bool operator==(const std::tuple<Ts...>& tuple, const Variant& variant)
287 {
288  return variant == tuple;
289 }
290 
291 //------------------------------------------------------------------------------
292 template <typename... Ts>
293 bool operator!=(const Variant& variant, const std::tuple<Ts...>& tuple)
294 {
295  return !variant.is<Array>() || variant.as<Array>() != tuple;
296 }
297 
298 //------------------------------------------------------------------------------
299 template <typename... Ts>
300 bool operator!=(const std::tuple<Ts...>& tuple, const Variant& variant)
301 {
302  return variant != tuple;
303 }
304 
305 } // namespace wamp
306 
307 #endif // CPPWAMP_TYPES_TUPLE_HPP
wamp::FromVariantConverter::variant
const Variant & variant() const
Returns a constant reference to the wrapped variant.
Definition: variant.hpp:1384
wamp::Variant::Array
wamp::Array Array
Dynamic array of variants.
Definition: variant.hpp:182
wamp::Variant
Discriminated union container that represents a JSON value.
Definition: variant.hpp:134
wamp::TypeId::array
@ array
For Variant::Array.
wamp::ToVariantConverter::variant
Variant & variant()
Returns a reference to the wrapped variant.
Definition: variant.hpp:1208
wamp
Definition: anyhandler.hpp:36
wamp::ToVariantConverter
Wrapper around a destination Variant, used for conversions.
Definition: variant.hpp:604
wamp::toTuple
void toTuple(const wamp::Variant::Array &array, std::tuple< Ts... > &tuple)
Converts a Variant::Array to a std::tuple.
Definition: tuple.hpp:211
wamp::Array
std::vector< Variant > Array
Variant bound type for arrays of variants.
Definition: variantdefs.hpp:51
wamp::FromVariantConverter
Wrapper around a source Variant, used for conversions.
Definition: variant.hpp:650
wamp::Variant::is
bool is() const
Returns true iff the variant's current dynamic type matches the given TBound type parameter.
Definition: variant.hpp:798
wamp::EnableIf
typename std::enable_if< B, T >::type EnableIf
Metafunction used to enable overloads based on a boolean condition.
Definition: traits.hpp:37
wamp::Variant::as
TBound & as()
Returns a reference to the variant's bound value.
Definition: variant.hpp:879
wamp::toArray
wamp::Variant::Array toArray(const std::tuple< Ts... > &tuple)
Converts a std::tuple to a Variant::Array.
Definition: tuple.hpp:219
wamp::convert
void convert(TConverter &c, TValue &val)
General function for converting custom types to/from Variant.
Definition: variant.hpp:709
wamp::error::Conversion
Exception type thrown when converting a Variant to an invalid type.
Definition: error.hpp:106
wamp::Variant::from
static Variant from(TValue &&value)
Constructs a variant from a custom type.
Definition: variant.hpp:744