Turi Create  4.0
flexible_type_detail.hpp
1 /* Copyright © 2017 Apple Inc. All rights reserved.
2  *
3  * Use of this source code is governed by a BSD-3-clause license that can
4  * be found in the LICENSE.txt file or at https://opensource.org/licenses/BSD-3-Clause
5  */
6 #ifndef TURI_FLEXIBLE_TYPE_DETAIL_HPP
7 #define TURI_FLEXIBLE_TYPE_DETAIL_HPP
8 #include <typeindex>
9 #include <sstream>
10 #include <cmath>
11 #include <string>
12 #include <core/logging/assertions.hpp>
13 #include <core/util/stl_util.hpp>
14 #include <core/util/cityhash_tc.hpp>
15 #include <core/storage/serialization/serialization_includes.hpp>
16 #include <core/data/flexible_type/flexible_type_base_types.hpp>
17 namespace boost { namespace posix_time {
18 class ptime;
19 } }
20 
21 namespace turi {
22 
23 namespace flexible_type_impl {
24 
25 /**
26  * custom implementation of conversion of ptime to time_t that handles
27  * time_t's that does not fit in int32_t integers.
28  */
29 boost::posix_time::ptime ptime_from_time_t(std::time_t offset, int32_t microseconds = 0);
30 
31 /**
32  * Function that takes a ptime argument and generates _
33  * its corresponding time_t.
34  */
35 flex_int ptime_to_time_t(const boost::posix_time::ptime & time);
36 
37 /**
38  * Takes a ptime argument and returns the fractional second component in us.
39  */
40 flex_int ptime_to_fractional_microseconds(const boost::posix_time::ptime & time);
41 
42 /**
43  * Helper for reading flex_date_time values from strings.
44  */
46 public:
47  /**
48  * Initializes this instance to read strings with the given format. If the
49  * format string is empty, then format "%Y%m%dT%H%M%S%F%q" is used.
50  */
51  explicit date_time_string_reader(std::string format);
52 
53  /**
54  * Returns the flex_date_time value parsed from `input`, or throws an
55  * exception if `input` could not be parsed using the format provided to the
56  * constructor.
57  */
58  flex_date_time read(const flex_string& input);
59 
60 private:
61  std::string format_;
62  std::istringstream stream_;
63 };
64 
65 /**
66  * \ingroup group_gl_flexible_type
67  * \internal
68  * Used to issue a static_assert only if instantiated.
69  */
70 template <bool b>
72  static_assert(b, "Invalid Type");
73 };
74 
75 
76 /**
77  * \ingroup group_gl_flexible_type
78  * \internal
79  * A wrapper to convert a binary visitor into a regular
80  * unary apply_visitor.
81  */
82 template <typename Visitor, typename U>
84  const Visitor& v;
85  const U& u;
86 
87  template <typename T>
88  inline FLEX_ALWAYS_INLINE_FLATTEN auto operator()(T& t) const -> decltype(v(t, u)) {
89  return v(t, u);
90  }
91 };
92 
93 
94 /**************************************************************************/
95 /* */
96 /* Visitors used throughout the flexible type implementation */
97 /* */
98 /**************************************************************************/
99 
100 
101 /**
102  * \ingroup group_gl_flexible_type
103  * \internal
104  * Handles less than comparison between flexible types
105  */
106 struct lt_operator {
107  template <typename T, typename U>
108  inline FLEX_ALWAYS_INLINE_FLATTEN bool operator()(T& t, const U& u) const { FLEX_TYPE_ASSERT(false); return false; }
109  inline FLEX_ALWAYS_INLINE_FLATTEN bool operator()(const flex_float t, const flex_float u) const { return t < u; }
110  inline FLEX_ALWAYS_INLINE_FLATTEN bool operator()(const flex_int t, const flex_int u) const { return t < u; }
111  inline FLEX_ALWAYS_INLINE_FLATTEN bool operator()(const flex_date_time t, const flex_int u) const { return t.posix_timestamp() < u; }
112  inline FLEX_ALWAYS_INLINE_FLATTEN bool operator()(const flex_int t, const flex_date_time u) const { return t < u.posix_timestamp(); }
113  inline FLEX_ALWAYS_INLINE_FLATTEN bool operator()(const flex_date_time t, const flex_float u) const { return t.microsecond_res_timestamp() < u; }
114  inline FLEX_ALWAYS_INLINE_FLATTEN bool operator()(const flex_float t, const flex_date_time u) const { return t < u.microsecond_res_timestamp(); }
115  inline FLEX_ALWAYS_INLINE_FLATTEN bool operator()(const flex_date_time& t, const flex_date_time& u) const { return t < u; }
116  inline FLEX_ALWAYS_INLINE_FLATTEN bool operator()(const flex_int t, const flex_float u) const { return t < u; }
117  inline FLEX_ALWAYS_INLINE_FLATTEN bool operator()(const flex_float t, const flex_int u) const { return t < u; }
118  inline FLEX_ALWAYS_INLINE_FLATTEN bool operator()(const std::string& t, const std::string& u) const { return t < u; }
119  inline FLEX_ALWAYS_INLINE_FLATTEN bool operator()(const flex_vec& t, const flex_vec& u) const {
120  // [1,2,3] < [1,2,3,4] true
121  // [1,2,3,4] < [1,2,3] false
122  // [1,2,3,4] < [1,2,3,4] false
123  for(size_t i = 0; i < t.size(); i++) {
124  if (u.size() <= i || t[i] > u[i]) return false;
125  if (t[i] < u[i]) return true;
126  }
127  return t.size() < u.size();
128  }
129 
130  inline bool operator()(const flex_list& t, const flex_list& u) const {
131  for(size_t i = 0; i < t.size(); i++) {
132  if (u.size() <= i || t[i] > u[i]) return false;
133  if (t[i] < u[i]) return true;
134  }
135  return t.size() < u.size();
136  }
137 };
138 
139 
140 
141 /**
142  * \ingroup group_gl_flexible_type
143  * \internal
144  * Handles greater than comparison between flexible types
145  */
146 struct gt_operator {
147  template <typename T, typename U>
148  inline FLEX_ALWAYS_INLINE_FLATTEN bool operator()(T& t, const U& u) const { FLEX_TYPE_ASSERT(false); return false; }
149  inline FLEX_ALWAYS_INLINE_FLATTEN bool operator()(const flex_float t, const flex_float u) const { return t > u; }
150  inline FLEX_ALWAYS_INLINE_FLATTEN bool operator()(const flex_date_time t, const flex_int u) const { return t.posix_timestamp() > u; }
151  inline FLEX_ALWAYS_INLINE_FLATTEN bool operator()(const flex_int t, const flex_date_time u) const { return t > u.posix_timestamp(); }
152  inline FLEX_ALWAYS_INLINE_FLATTEN bool operator()(const flex_date_time t, const flex_float u) const { return t.microsecond_res_timestamp() > u; }
153  inline FLEX_ALWAYS_INLINE_FLATTEN bool operator()(const flex_float t, const flex_date_time u) const { return t > u.microsecond_res_timestamp(); }
154  inline FLEX_ALWAYS_INLINE_FLATTEN bool operator()(const flex_date_time& t, const flex_date_time& u) const { return t > u; }
155  inline FLEX_ALWAYS_INLINE_FLATTEN bool operator()(const flex_int t, const flex_int u) const { return t > u; }
156  inline FLEX_ALWAYS_INLINE_FLATTEN bool operator()(const flex_int t, const flex_float u) const { return t > u; }
157  inline FLEX_ALWAYS_INLINE_FLATTEN bool operator()(const flex_float t, const flex_int u) const { return t > u; }
158  inline FLEX_ALWAYS_INLINE_FLATTEN bool operator()(const std::string& t, const std::string& u) const { return t > u; }
159  inline FLEX_ALWAYS_INLINE_FLATTEN bool operator()(const flex_vec& t, const flex_vec& u) const {
160  for(size_t i = 0; i < t.size(); i++) {
161  if (u.size() <= i || t[i] > u[i]) return true;
162  if (t[i] < u[i]) return false;
163  }
164 
165  return t.size() > u.size();
166  }
167 
168  inline bool operator()(const flex_list& t, const flex_list& u) const {
169  for(size_t i = 0; i < t.size(); i++) {
170  if (u.size() <= i || t[i] > u[i]) return true;
171  if (t[i] < u[i]) return false;
172  }
173  return t.size() > u.size();
174  }
175 };
176 
177 
178 
179 /**
180  * \ingroup group_gl_flexible_type
181  * \internal
182  * Handles equality comparison between flexible types.
183  * They must be identical for the comparison to return true;
184  */
186  template <typename T, typename U>
187  inline FLEX_ALWAYS_INLINE_FLATTEN bool operator()(T& t, const U& u) const { return false; }
188  inline FLEX_ALWAYS_INLINE_FLATTEN bool operator()(const flex_date_time t, const flex_date_time u) const { return t == u; }
189  inline FLEX_ALWAYS_INLINE_FLATTEN bool operator()(const flex_date_time t, const flex_int u) const { return t.posix_timestamp() == u && t.microsecond() == 0; }
190  inline FLEX_ALWAYS_INLINE_FLATTEN bool operator()(const flex_int t, const flex_date_time u) const { return t == u.posix_timestamp() && u.microsecond() == 0; }
191  inline FLEX_ALWAYS_INLINE_FLATTEN bool operator()(const flex_date_time t, const flex_float u) const {
192  return std::fabs(t.microsecond_res_timestamp() - u) < flex_date_time::MICROSECOND_EPSILON;
193  }
194  inline FLEX_ALWAYS_INLINE_FLATTEN bool operator()(const flex_float t, const flex_date_time u) const {
195  return std::fabs(t - u.microsecond_res_timestamp()) < flex_date_time::MICROSECOND_EPSILON;
196  }
197  inline FLEX_ALWAYS_INLINE_FLATTEN bool operator()(const flex_int t, const flex_int u) const { return t == u; }
198  inline FLEX_ALWAYS_INLINE_FLATTEN bool operator()(const flex_float t, const flex_float u) const { return t == u; }
199  inline FLEX_ALWAYS_INLINE_FLATTEN bool operator()(const flex_string& t, const flex_string& u) const { return t == u; }
200  inline FLEX_ALWAYS_INLINE_FLATTEN bool operator()(const flex_image& t, const flex_image& u) const { return t == u; }
201  inline FLEX_ALWAYS_INLINE_FLATTEN bool operator()(const flex_vec& t, const flex_vec& u) const {
202  if (t.size() != u.size()) return false;
203  for (size_t i = 0;i < t.size(); ++i) if (t[i] != u[i]) return false;
204  return true;
205  }
206  // Just use operator== which calls the approx_equality_operator
207  inline FLEX_ALWAYS_INLINE_FLATTEN bool operator()(const flex_dict& t, const flex_dict& u) const {
208  return t == u;
209  };
210  inline FLEX_ALWAYS_INLINE_FLATTEN bool operator()(const flex_list& t, const flex_list& u) const {
211  return t == u;
212  };
213 
214  inline FLEX_ALWAYS_INLINE_FLATTEN bool operator()(flex_undefined t, flex_undefined u) const {
215  return true;
216  };
217  inline FLEX_ALWAYS_INLINE_FLATTEN bool operator()(const flex_nd_vec& t, const flex_nd_vec& u) const {
218  return t == u;
219  }
220 };
221 
222 
223 /**
224  * \ingroup group_gl_flexible_type
225  * \internal
226  * A looser version of the equality operator which allows checking between
227  * for equality between integer and floating point types
228  */
230  template <typename T, typename U>
231  inline FLEX_ALWAYS_INLINE_FLATTEN bool operator()(T& t, const U& u) const { return false; }
232  inline FLEX_ALWAYS_INLINE_FLATTEN bool operator()(const flex_undefined t, const flex_undefined u) const { return true; }
233  inline FLEX_ALWAYS_INLINE_FLATTEN bool operator()(const flex_date_time t, const flex_date_time u) const { return t == u; }
234  inline FLEX_ALWAYS_INLINE_FLATTEN bool operator()(const flex_date_time t, const flex_int u) const { return t.posix_timestamp() == u && t.microsecond() == 0; }
235  inline FLEX_ALWAYS_INLINE_FLATTEN bool operator()(const flex_int t, const flex_date_time u) const { return t == u.posix_timestamp() && u.microsecond() == 0; }
236  inline FLEX_ALWAYS_INLINE_FLATTEN bool operator()(const flex_date_time t, const flex_float u) const {
237  return std::fabs(t.microsecond_res_timestamp() - u) < flex_date_time::MICROSECOND_EPSILON;
238  }
239  inline FLEX_ALWAYS_INLINE_FLATTEN bool operator()(const flex_float t, const flex_date_time u) const {
240  return std::fabs(t - u.microsecond_res_timestamp()) < flex_date_time::MICROSECOND_EPSILON;
241  }
242  inline FLEX_ALWAYS_INLINE_FLATTEN bool operator()(const flex_int t, const flex_int u) const { return t == u; }
243  inline FLEX_ALWAYS_INLINE_FLATTEN bool operator()(const flex_float t, const flex_float u) const {
244  return (std::isnan(t) && std::isnan(u)) || (t == u);
245  }
246  inline FLEX_ALWAYS_INLINE_FLATTEN bool operator()(const flex_int t, const flex_float u) const { return t == u; }
247  inline FLEX_ALWAYS_INLINE_FLATTEN bool operator()(const flex_float t, const flex_int u) const { return t == u; }
248  inline FLEX_ALWAYS_INLINE_FLATTEN bool operator()(const flex_string& t, const flex_string& u) const { return t == u; }
249  inline FLEX_ALWAYS_INLINE_FLATTEN bool operator()(const flex_image& t, const flex_image& u) const { return t == u; }
250  inline FLEX_ALWAYS_INLINE_FLATTEN bool operator()(const flex_vec& t, const flex_vec& u) const {
251  if (t.size() != u.size()) return false;
252  for (size_t i = 0;i < t.size(); ++i) if (t[i] != u[i]) return false;
253  return true;
254  }
255  inline FLEX_ALWAYS_INLINE_FLATTEN bool operator()(const flex_nd_vec& t, const flex_nd_vec& u) const {
256  return t == u;
257  }
258  // Implemented in flexible_type.cpp
259  bool operator()(const flex_dict& t, const flex_dict& u) const;
260  bool operator()(const flex_list& t, const flex_list& u) const;
261 };
262 
263 
264 /**
265  * \ingroup group_gl_flexible_type
266  * \internal
267  * Handles negation of a flexible type
268  */
270  template <typename T>
271  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(T& t) const {
272  FLEX_TYPE_ASSERT(false);
273  }
274  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_int& t) const { t = -t; }
275  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_float& t) const { t = -t; }
276  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_vec& t) const {
277  for (size_t i = 0;i < t.size(); ++i) t[i] = -t[i];
278  }
279  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_nd_vec& t) const {
280  t.negate();
281  }
282 };
283 
284 
285 
286 /**
287  * \ingroup group_gl_flexible_type
288  * \internal
289  * Handles increment of a flexible type
290  */
292  template <typename T>
293  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(T& t) const {
294  FLEX_TYPE_ASSERT(false);
295  }
296  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_int& t) const { t++; }
297  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_float& t) const { t++; }
298 };
299 
300 
301 /**
302  * \ingroup group_gl_flexible_type
303  * \internal
304  * Handles decrement of a flexible type
305  */
307  template <typename T>
308  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(T& t) const {
309  FLEX_TYPE_ASSERT(false);
310  }
311  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_int& t) const { t--; }
312  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_float& t) const { t--; }
313 };
314 
315 
316 
317 /**
318  * \ingroup group_gl_flexible_type
319  * \internal
320  * Handles += between flexible types
321  */
323  template <typename T, typename U>
324  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(T& t, const U& u) const { FLEX_TYPE_ASSERT(false); }
325  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_int& t, const flex_int u) const { t += u; }
326  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_date_time& t, const flex_int u) const { t.set_posix_timestamp(t.posix_timestamp() + u); }
327  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_date_time& t, const flex_float u) const {
328  int64_t integral_part = std::floor(u);
329  int64_t us_part = (u - integral_part) * flex_date_time::MICROSECONDS_PER_SECOND;
330  t.set_posix_timestamp(t.posix_timestamp() + integral_part);
331  auto microsecond = t.microsecond() + us_part;
332  if (microsecond >= flex_date_time::MICROSECONDS_PER_SECOND) {
334  microsecond -= flex_date_time::MICROSECONDS_PER_SECOND;
335  }
336  t.set_microsecond(static_cast<uint32_t>(microsecond));
337  }
338  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_int& t, const flex_float u) const { t += u; }
339  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_float& t, const flex_int u) const { t += u; }
340  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_float& t, const flex_float u) const { t += u; }
341  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(std::string& t, const std::string& u) const { t += u; }
342  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_vec& t, const flex_vec& u) const {
343  FLEX_TYPE_ASSERT(t.size() == u.size());
344  for (size_t i = 0;i < t.size(); ++i) t[i] += u[i];
345  }
346 
347  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_vec& t, const flex_int u) const {
348  for (size_t i = 0;i < t.size(); ++i) t[i] += u;
349  }
350 
351  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_vec& t, const flex_float u) const {
352  for (size_t i = 0;i < t.size(); ++i) t[i] += u;
353  }
354  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_nd_vec& t, const flex_int u) const {
355  t += flex_float(u);
356  }
357  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_nd_vec& t, const flex_float u) const {
358  t += u;
359  }
360  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_nd_vec& t, const flex_nd_vec& u) const {
361  t += u;
362  }
363 };
364 
365 
366 /**
367  * \ingroup group_gl_flexible_type
368  * \internal
369  * Handles -= between flexible types
370  */
372  template <typename T, typename U>
373  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(T& t, const U& u) const { FLEX_TYPE_ASSERT(false); }
374  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_date_time& t, const flex_int u) const { t.set_posix_timestamp(t.posix_timestamp() - u); }
375  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_date_time& t, const flex_float u) const {
376  int64_t integral_part = std::floor(u);
377  int64_t us_part = (u - integral_part) * flex_date_time::MICROSECONDS_PER_SECOND;
378  t.set_posix_timestamp(t.posix_timestamp() - integral_part);
379  auto microsecond = t.microsecond() - us_part;
380  if (microsecond < 0) {
382  microsecond += flex_date_time::MICROSECONDS_PER_SECOND;
383  }
384  t.set_microsecond(static_cast<uint32_t>(microsecond));
385  }
386  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_int& t, const flex_int& u) const { t -= u; }
387  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_int& t, const flex_float& u) const { t -= u; }
388  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_float& t, const flex_int& u) const { t -= u; }
389  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_float& t, const flex_float& u) const { t -= u; }
390  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_vec& t, const flex_vec& u) const {
391  FLEX_TYPE_ASSERT(t.size() == u.size());
392  for (size_t i = 0;i < t.size(); ++i) t[i] -= u[i];
393  }
394 
395  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_vec& t, const flex_int u) const {
396  for (size_t i = 0;i < t.size(); ++i) t[i] -= u;
397  }
398 
399  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_vec& t, const flex_float u) const {
400  for (size_t i = 0;i < t.size(); ++i) t[i] -= u;
401  }
402  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_nd_vec& t, const flex_int u) const {
403  t -= flex_float(u);
404  }
405  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_nd_vec& t, const flex_float u) const {
406  t -= u;
407  }
408  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_nd_vec& t, const flex_nd_vec& u) const {
409  t -= u;
410  }
411 };
412 
413 
414 /**
415  * \ingroup group_gl_flexible_type
416  * \internal
417  * Handles /= between flexible types
418  */
420  template <typename T, typename U>
421  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(T& t, const U& u) const { FLEX_TYPE_ASSERT(false); }
422 
423  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_int& t, const flex_int& u) const { t /= u; }
424  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_int& t, const flex_float& u) const { t /= u; }
425  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_float& t, const flex_int& u) const { t /= u; }
426  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_float& t, const flex_float& u) const { t /= u; }
427 
428  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_vec& t, const flex_vec& u) const {
429  FLEX_TYPE_ASSERT(t.size() == u.size());
430  for (size_t i = 0;i < t.size(); ++i) t[i] /= u[i];
431  }
432  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_vec& t, const flex_int u) const {
433  for (size_t i = 0;i < t.size(); ++i) t[i] /= u;
434  }
435 
436  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_vec& t, const flex_float u) const {
437  for (size_t i = 0;i < t.size(); ++i) t[i] /= u;
438  }
439  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_nd_vec& t, const flex_int u) const {
440  t /= flex_float(u);
441  }
442  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_nd_vec& t, const flex_float u) const {
443  t /= u;
444  }
445  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_nd_vec& t, const flex_nd_vec& u) const {
446  t /= u;
447  }
448 };
449 
450 
451 
452 /**
453  * \ingroup group_gl_flexible_type
454  * \internal
455  * Handles %= between flexible types
456  */
458  template <typename T, typename U>
459  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(T& t, const U& u) const { FLEX_TYPE_ASSERT(false); }
460 
461  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_int& t, const flex_int& u) const { t %= u; }
462  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_int& t, const flex_float& u) const { t %= (flex_int)u; }
463  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_float& t, const flex_int& u) const { t = fmod(t, u); }
464  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_float& t, const flex_float& u) const { t = fmod(t, u); }
465  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_vec& t, const flex_vec& u) const {
466  FLEX_TYPE_ASSERT(t.size() == u.size());
467  for (size_t i = 0;i < t.size(); ++i) t[i] = fmod(t[i], u[i]);
468  }
469 
470  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_vec& t, const flex_int u) const {
471  for (size_t i = 0;i < t.size(); ++i) t[i] = fmod(t[i], u);
472  }
473  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_vec& t, const flex_float u) const {
474  for (size_t i = 0;i < t.size(); ++i) t[i] = fmod(t[i], u);
475  }
476  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_nd_vec& t, const flex_nd_vec& u) const {
477  t %= u;
478  }
479 
480  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_nd_vec& t, const flex_int u) const {
481  t %= u;
482  }
483  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_nd_vec& t, const flex_float u) const {
484  t %= u;
485  }
486 };
487 
488 
489 /**
490  * \ingroup group_gl_flexible_type
491  * \internal
492  * Handles *= between flexible types
493  */
495  template <typename T, typename U>
496  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(T& t, const U& u) const { FLEX_TYPE_ASSERT(false); }
497 
498  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_int& t, const flex_int& u) const { t *= u; }
499  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_int& t, const flex_float& u) const { t *= u; }
500  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_float& t, const flex_int& u) const { t *= u; }
501  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_float& t, const flex_float& u) const { t *= u; }
502  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_vec& t, const flex_vec& u) const {
503  FLEX_TYPE_ASSERT(t.size() == u.size());
504  for (size_t i = 0;i < t.size(); ++i) t[i] *= u[i];
505  }
506 
507  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_vec& t, const flex_int u) const {
508  for (size_t i = 0;i < t.size(); ++i) t[i] *= u;
509  }
510 
511  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_vec& t, const flex_float u) const {
512  for (size_t i = 0;i < t.size(); ++i) t[i] *= u;
513  }
514  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_nd_vec& t, const flex_int u) const {
515  t *= flex_float(u);
516  }
517  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_nd_vec& t, const flex_float u) const {
518  t *= u;
519  }
520  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_nd_vec& t, const flex_nd_vec& u) const {
521  t *= u;
522  }
523 };
524 
525 
526 /**
527  * \ingroup group_gl_flexible_type
528  * \internal
529  * Converts the stored value to a flex_date_time format
530  */
532  template <typename T>
533  inline FLEX_ALWAYS_INLINE_FLATTEN flex_date_time operator()(T t) const { FLEX_TYPE_ASSERT(false); return flex_date_time(); }
534  inline FLEX_ALWAYS_INLINE_FLATTEN flex_date_time operator()(flex_undefined t) const { return flex_date_time(); }
535  inline FLEX_ALWAYS_INLINE_FLATTEN flex_date_time operator()(flex_int i) const {
536  return flex_date_time(i);
537  }
538  inline FLEX_ALWAYS_INLINE_FLATTEN flex_date_time operator()(const flex_date_time& dt) const {
539  return dt;
540  }
541  inline FLEX_ALWAYS_INLINE_FLATTEN flex_date_time operator()(flex_float i) const {
542  flex_date_time ret;
544  return ret;
545  }
546  flex_date_time operator()(const flex_string& s) const;
547 };
548 
549 
550 /**
551  * \ingroup group_gl_flexible_type
552  * \internal
553  * Converts the stored value to an integer
554  */
556  template <typename T>
557  inline FLEX_ALWAYS_INLINE_FLATTEN flex_int operator()(T t) const { FLEX_TYPE_ASSERT(false); return 0; }
558  inline FLEX_ALWAYS_INLINE_FLATTEN flex_int operator()(flex_undefined t) const { return 0; }
559  inline FLEX_ALWAYS_INLINE_FLATTEN flex_int operator()(flex_int i) const {return i; }
560  inline FLEX_ALWAYS_INLINE_FLATTEN flex_int operator()(flex_date_time dt) const {
561  return dt.posix_timestamp();
562  }
563  inline FLEX_ALWAYS_INLINE_FLATTEN flex_int operator()(flex_float i) const {return i; }
564  inline FLEX_ALWAYS_INLINE_FLATTEN flex_int operator()(const flex_string& t) const {
565  size_t end_index;
566  long long int converted = std::stoll(t.data(), &end_index);
567  if (end_index != t.length()) {
568  // was not at end of element so throw error
569  throw std::runtime_error("Invalid conversion: " + t + " cannot be interpreted as an integer");
570  } else {
571  return converted;
572  }
573  }
574 };
575 
576 /**
577  * \ingroup group_gl_flexible_type
578  * \internal
579  * Converts the stored value to a flex_float
580  */
582  template <typename T>
583  inline FLEX_ALWAYS_INLINE_FLATTEN flex_float operator()(T t) const { FLEX_TYPE_ASSERT(false); return 0.0; }
584  inline FLEX_ALWAYS_INLINE_FLATTEN flex_float operator()(flex_undefined t) const { return 0.0; }
585  inline FLEX_ALWAYS_INLINE_FLATTEN flex_float operator()(flex_date_time dt) const {
586  return dt.microsecond_res_timestamp();
587  }
588  inline FLEX_ALWAYS_INLINE_FLATTEN flex_float operator()(flex_int i) const {return i; }
589  inline FLEX_ALWAYS_INLINE_FLATTEN flex_float operator()(flex_float i) const {return i; }
590  inline FLEX_ALWAYS_INLINE_FLATTEN flex_float operator()(const flex_string& t) const {
591  size_t end_index;
592  double converted = std::stod(t.data(), &end_index);
593  if (end_index != t.length()) {
594  // was not at end of element so throw error
595  throw std::runtime_error("Invalid conversion: " + t + " cannot be interpreted as a float");
596  } else {
597  return (float)converted;
598  }
599  }
600 };
601 
602 
603 
604 /**
605  * \ingroup group_gl_flexible_type
606  * \internal
607  * Converts the stored value to a flex_string
608  */
610  inline FLEX_ALWAYS_INLINE_FLATTEN flex_string operator()(flex_undefined u) const { return flex_string(); }
611  inline FLEX_ALWAYS_INLINE_FLATTEN flex_string operator()(flex_float i) const { return tostr(i); }
612  inline FLEX_ALWAYS_INLINE_FLATTEN flex_string operator()(flex_int i) const { return tostr(i); }
613  flex_string operator()(const flex_date_time& i) const;
614  inline FLEX_ALWAYS_INLINE_FLATTEN flex_string operator()(const flex_string& i) const { return i; }
615 
616  flex_string operator()(const flex_vec& vec) const;
617  flex_string operator()(const flex_list& vec) const;
618  flex_string operator()(const flex_dict& vec) const;
619  flex_string operator()(const flex_image& vec) const;
620  flex_string operator()(const flex_nd_vec& vec) const;
621 };
622 
623 
624 /**
625  * \ingroup group_gl_flexible_type
626  * \internal
627  * Converts the stored value to a flex_vec
628  */
630  template <typename T>
631  inline FLEX_ALWAYS_INLINE_FLATTEN flex_vec operator()(T t) const { FLEX_TYPE_ASSERT(false); return flex_vec(); }
632  inline FLEX_ALWAYS_INLINE_FLATTEN flex_vec operator()(flex_undefined t) const { return flex_vec(); }
633  inline FLEX_ALWAYS_INLINE_FLATTEN flex_vec operator()(flex_int i) const {return flex_vec{(double)i}; }
634  inline FLEX_ALWAYS_INLINE_FLATTEN flex_vec operator()(flex_float i) const {return flex_vec{i}; }
635  inline FLEX_ALWAYS_INLINE_FLATTEN flex_vec operator()(const flex_vec& i) const {return i; }
636  inline FLEX_ALWAYS_INLINE_FLATTEN flex_vec operator()(flex_date_time i) const {return flex_vec{get_float_visitor()(i)}; }
637  inline FLEX_ALWAYS_INLINE_FLATTEN flex_vec operator()(const flex_nd_vec& i) const {
638  if (i.is_full()) {
639  return i.elements();
640  } else {
641  flex_nd_vec tmp = i.compact();
642  return tmp.elements();
643  }
644  }
645 
646  flex_vec operator()(const flex_image& img) const;
647 };
648 
649 
650 /**
651  * \ingroup group_gl_flexible_type
652  * \internal
653  * Converts the stored value to a flex_nd_vec
654  */
656  template <typename T>
657  inline FLEX_ALWAYS_INLINE_FLATTEN flex_nd_vec operator()(T t) const { FLEX_TYPE_ASSERT(false); return flex_vec(); }
658  inline FLEX_ALWAYS_INLINE_FLATTEN flex_nd_vec operator()(flex_undefined t) const { return flex_vec(); }
659  inline FLEX_ALWAYS_INLINE_FLATTEN flex_nd_vec operator()(flex_int i) const {return flex_nd_vec({(double)i}); }
660  inline FLEX_ALWAYS_INLINE_FLATTEN flex_nd_vec operator()(flex_float i) const {return flex_nd_vec({i}); }
661  inline FLEX_ALWAYS_INLINE_FLATTEN flex_nd_vec operator()(const flex_vec& i) const {return flex_nd_vec(i); }
662  inline FLEX_ALWAYS_INLINE_FLATTEN flex_nd_vec operator()(flex_date_time i) const {return flex_nd_vec({get_float_visitor()(i)}); }
663  inline FLEX_ALWAYS_INLINE_FLATTEN flex_nd_vec operator()(const flex_nd_vec& i) const { return i; }
664  flex_nd_vec operator()(flex_list i) const;
665  flex_nd_vec operator()(const flex_image& img) const;
666 };
667 
668 /**
669  * \ingroup group_gl_flexible_type
670  * \internal
671  * Converts the stored value to a flex_list
672  */
674  template <typename T>
675  inline FLEX_ALWAYS_INLINE_FLATTEN flex_list operator()(T t) const { FLEX_TYPE_ASSERT(false); return flex_list(); }
676  inline FLEX_ALWAYS_INLINE_FLATTEN flex_list operator()(flex_undefined t) const { return flex_list(); }
677  inline FLEX_ALWAYS_INLINE_FLATTEN flex_list operator()(flex_date_time i) const {
678  return flex_list{get_float_visitor()(i)}; }
679  inline FLEX_ALWAYS_INLINE_FLATTEN flex_list operator()(flex_int i) const {
680  return flex_list{flexible_type(i)}; }
681  inline FLEX_ALWAYS_INLINE_FLATTEN flex_list operator()(flex_float i) const {
682  return flex_list{flexible_type(i)}; }
683  inline FLEX_ALWAYS_INLINE_FLATTEN flex_list operator()(const flex_string& i) const {
684  return flex_list{flexible_type(i)}; }
685  inline FLEX_ALWAYS_INLINE_FLATTEN flex_list operator()(const flex_vec& v) const {
686  flex_list r(v.size());
687  for(size_t i = 0; i < v.size(); ++i)
688  r[i] = v[i];
689  return r;
690  }
691  inline FLEX_ALWAYS_INLINE_FLATTEN flex_list operator()(const flex_list& v) const {
692  return v;
693  }
694 };
695 
696 /**
697  * \ingroup group_gl_flexible_type
698  * \internal
699  * Converts the stored value to a flex_dict
700  */
702  template <typename T>
703  inline FLEX_ALWAYS_INLINE_FLATTEN flex_dict operator()(T t) const { FLEX_TYPE_ASSERT(false); return flex_dict(); }
704  inline FLEX_ALWAYS_INLINE_FLATTEN flex_dict operator()(flex_undefined t) const { return flex_dict(); }
705  inline FLEX_ALWAYS_INLINE_FLATTEN flex_dict operator()(const flex_dict& v) const { return v; }
706 };
707 
708 /**
709  * \ingroup group_gl_flexible_type
710  * \internal
711  * Converts the stored value to a flex_image
712  */
714  template <typename T>
715  inline FLEX_ALWAYS_INLINE_FLATTEN flex_image operator()(T t) const { FLEX_TYPE_ASSERT(false); return flex_image(); }
716  inline FLEX_ALWAYS_INLINE_FLATTEN flex_image operator()(flex_undefined t) const { return flex_image(); }
717  inline FLEX_ALWAYS_INLINE_FLATTEN flex_image operator()(const flex_image& v) const { return v; }
718  flex_image operator()(const flex_nd_vec& v) const;
719 
720 };
721 
722 /**
723  * \ingroup group_gl_flexible_type
724  * \internal
725  * Soft assignment between flexible types
726  *
727  * \note Changes to this should update \ref flex_type_is_convertible.
728  */
730  template <typename T, typename U>
731  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(T& t, const U& u) const { FLEX_TYPE_ASSERT(false); }
732 
733  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_date_time& t, const flex_int u) const {
734  t = flex_date_time(u);
735  }
736  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_int& t, const flex_date_time u) const { t = get_int_visitor()(u); }
737  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_float& t, const flex_date_time u) const { t = get_float_visitor()(u); }
738  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_date_time& t, const flex_float u) const {
739  flex_date_time dt;
741  t = dt;
742  }
743  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_date_time& t, const flex_date_time u) const { t = u; }
744  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_string& t, const flex_date_time u) const { t = get_string_visitor()(u); }
745  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_int& t, const flex_int u) const { t = u; }
746  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_float& t, const flex_float u) const { t = u; }
747  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_int& t, const flex_float u) const { t = u; }
748  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_float& t, const flex_int u) const { t = u; }
749  template <typename U>
750  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_string& t, const U& u) const { t = get_string_visitor()(u); }
751  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_vec& t, const flex_vec& u) const { t = u; }
752  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_list& t, const flex_list& u) const { t = u; }
753  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_list& t, const flex_vec& u) const { t.assign(u.begin(), u.end()); }
754  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_dict& t, const flex_dict& u) const { t = u; }
755  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_undefined& t, const flex_undefined& u) const { t = u; }
756  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_float& t, const flex_undefined& u) const { t = NAN; }
757  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_vec& t, const flex_image& u) const { t = get_vec_visitor()(u); }
758  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_nd_vec& t, const flex_nd_vec& u) const { t = u; }
759  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_nd_vec& t, const flex_vec& u) const { t = get_ndvec_visitor()(u); }
760  FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_nd_vec& t, const flex_list& u) const { t= get_ndvec_visitor()(u); }
761  FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_nd_vec& t, const flex_image& u) const { t= get_ndvec_visitor()(u); }
762  FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_image& t, const flex_nd_vec& u) const { t= get_img_visitor()(u); }
763  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(flex_vec& t, const flex_nd_vec& u) const {
764  if (u.is_full()) {
765  t = u.elements();
766  } else {
767  flex_nd_vec tmp = u.compact();
768  t = tmp.elements();
769  }
770  }
771 
772  // In flexible_type.cpp
773  void operator()(flex_vec& t, const flex_list& u) const;
774 };
775 
776 /**
777  * \ingroup group_gl_flexible_type
778  * \internal
779  * Serializes the contents of the flexible type
780  */
781 struct serializer {
782  oarchive& oarc;
783  template <typename T>
784  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(const T& i) const { oarc << i; }
785 };
786 
787 
788 /**
789  * \ingroup group_gl_flexible_type
790  * \internal
791  * Deserializes the contents of the flexible type
792  */
793 struct deserializer {
794  iarchive& iarc;
795  template <typename T>
796  inline FLEX_ALWAYS_INLINE_FLATTEN void operator()(T& i) const { iarc >> i; }
797 };
798 
799 
800 
801 /**
802  * \ingroup group_gl_flexible_type
803  * \internal
804  * Get the type index of the underlying contents
805  */
807  template <typename T>
808  inline FLEX_ALWAYS_INLINE_FLATTEN std::type_index operator()(T& i) const { return typeid(i); }
809 };
810 
811 
812 // /**
813 // * Computes a hash of the flexible type. Uses MD5
814 // */
815 // struct md5_hash_visitor {
816 // template <typename T>
817 // size_t operator()(T t) const {
818 // return 0;
819 // }
820 // size_t operator()(flex_int t) const {
821 // return t;
822 // }
823 // size_t operator()(const flex_float& t) const {
824 // return *reinterpret_cast<const size_t*>(&t);
825 // }
826 // size_t operator()(const flex_string& t) const {
827 // uint64_t md5low, md5high;
828 // mg_md5_buf(&md5low, &md5high, t.c_str(), t.length());
829 // return md5low;
830 // }
831 // size_t operator()(const flex_vec& t) const {
832 // uint64_t md5low, md5high;
833 // mg_md5_buf(&md5low, &md5high,
834 // reinterpret_cast<const char*>(t.data()),
835 // t.size() * sizeof(flex_vec::value_type));
836 // return md5low;
837 // }
838 // };
839 //
840 
841 
842 /**
843  * \ingroup group_gl_flexible_type
844  * \internal
845  * Computes a hash of the flexible type. Uses cityhash
846  */
848  template <typename T>
849  inline FLEX_ALWAYS_INLINE_FLATTEN size_t operator()(T t) const {
850  return 0;
851  }
852  inline FLEX_ALWAYS_INLINE_FLATTEN size_t operator()(flex_int t) const {
853  return turi::hash64(t);
854  }
855  inline FLEX_ALWAYS_INLINE_FLATTEN size_t operator()(flex_date_time t) const {
856  auto ret = turi::hash64_combine(
860  }
861  inline FLEX_ALWAYS_INLINE_FLATTEN size_t operator()(const flex_float& t) const {
862  flex_float t2 = std::isnan(t) ? NAN : t;
863  size_t t2_int;
864  static_assert(sizeof(flex_float) == sizeof(size_t), "sizeof(flex_float) == sizeof(size_t)");
865  memcpy(&t2_int, &t2, sizeof(size_t));
866  return turi::hash64(t2_int);
867  }
868  inline FLEX_ALWAYS_INLINE_FLATTEN size_t operator()(const flex_string& t) const {
869  return turi::hash64(t);
870  }
871  inline FLEX_ALWAYS_INLINE_FLATTEN size_t operator()(const flex_vec& t) const {
872  return turi::hash64(reinterpret_cast<const char*>(t.data()),
873  t.size() * sizeof(flex_vec::value_type));
874  }
875  inline FLEX_ALWAYS_INLINE_FLATTEN size_t operator()(const flex_nd_vec& t) const {
876  return turi::hash64(reinterpret_cast<const char*>(t.raw_elements().data()),
877  t.raw_elements().size() * sizeof(flex_nd_vec::value_type));
878  }
879  // Implemented in flexible_type.cpp
880  size_t operator()(const flex_list& t) const;
881  size_t operator()(const flex_dict& t) const;
882 };
883 
884 /**
885  * \ingroup group_gl_flexible_type
886  * \internal
887  * Computes a hash of the flexible type. Uses MD5
888  */
890  template <typename T>
891  inline FLEX_ALWAYS_INLINE_FLATTEN uint128_t operator()(T t) const {
892  return 0;
893  }
894  inline FLEX_ALWAYS_INLINE_FLATTEN uint128_t operator()(flex_date_time t) const {
895  auto ret = turi::hash128_combine(
899  }
900  inline FLEX_ALWAYS_INLINE_FLATTEN uint128_t operator()(flex_int t) const {
901  return turi::hash128((long long)(t));
902  }
903  inline FLEX_ALWAYS_INLINE_FLATTEN uint128_t operator()(const flex_float& t) const {
904  flex_float t2 = std::isnan(t) ? NAN : t;
905  size_t t2_int;
906  static_assert(sizeof(flex_float) == sizeof(size_t), "sizeof(flex_float) == sizeof(size_t)");
907  memcpy(&t2_int, &t2, sizeof(size_t));
908  return turi::hash128(t2_int);
909  }
910  inline FLEX_ALWAYS_INLINE_FLATTEN uint128_t operator()(const flex_string& t) const {
911  return turi::hash128(t);
912  }
913  inline FLEX_ALWAYS_INLINE_FLATTEN uint128_t operator()(const flex_vec& t) const {
914  return turi::hash128(reinterpret_cast<const char*>(t.data()),
915  t.size() * sizeof(flex_vec::value_type));
916  }
917  inline FLEX_ALWAYS_INLINE_FLATTEN uint128_t operator()(const flex_nd_vec& t) const {
918  return turi::hash128(reinterpret_cast<const char*>(t.raw_elements().data()),
919  t.raw_elements().size() * sizeof(flex_nd_vec::value_type));
920  }
921 
922  // Implemented in flexible_type.cpp
923  uint128_t operator()(const flex_list& t) const;
924  uint128_t operator()(const flex_dict& t) const;
925 };
926 
927 
928 
929 } // flexible_type_impl
930 
931 } // turicreate
932 
933 #endif
void set_microsecond_res_timestamp(double d)
std::vector< double > flex_vec
void set_microsecond(int32_t microsecond)
static uint128_t hash128(const char *s, size_t len)
The serialization input archive object which, provided with a reference to an istream, will read from the istream, providing deserialization capabilities.
Definition: iarchive.hpp:60
static uint64_t hash64_combine(uint64_t h1, uint64_t h2)
container_type & elements()
Definition: ndarray.hpp:295
ndarray< T > compact() const
Definition: ndarray.hpp:489
flexible_type_impl::ndarray< double > flex_nd_vec
static uint128_t hash128_combine(uint128_t h1, uint128_t h2)
container_type & raw_elements()
Definition: ndarray.hpp:276
static uint64_t hash64(const char *s, size_t len)
std::string flex_string
ndarray< T > & negate()
negation
Definition: ndarray.hpp:683
image_type flex_image
std::string tostr(const T &t)
Definition: stl_util.hpp:459
The serialization output archive object which, provided with a reference to an ostream, will write to the ostream, providing serialization capabilities.
Definition: oarchive.hpp:80
std::vector< std::pair< flexible_type, flexible_type > > flex_dict
std::vector< flexible_type > flex_list