Flexiv AIDK APIs  1.2
variant.hpp
Go to the documentation of this file.
1 
8 #include <chrono>
9 #include <iostream>
10 #include <memory>
11 #include <thread>
12 #include <typeindex>
13 #include <unordered_map>
14 #include <vector>
15 
16 namespace flexiv {
17 namespace ai {
18 
19 // Custom variant inplementation for different types
20 template <size_t arg1, size_t... others>
21 struct static_max;
22 
23 template <size_t arg>
24 struct static_max<arg>
25 {
26  static const size_t value = arg;
27 };
28 
29 template <size_t arg1, size_t arg2, size_t... others>
30 struct static_max<arg1, arg2, others...>
31 {
32  static const size_t value = arg1 >= arg2
33  ? static_max<arg1, others...>::value
34  : static_max<arg2, others...>::value;
35 };
36 
37 template <typename... Ts>
38 struct variant_helper;
39 
40 template <typename F, typename... Ts>
41 struct variant_helper<F, Ts...>
42 {
43  inline static void destroy(size_t id, void *data)
44  {
45  if (id == typeid(F).hash_code())
46  reinterpret_cast<F *>(data)->~F();
47  else
49  }
50 
51  inline static void move(size_t old_t, void *old_v, void *new_v)
52  {
53  if (old_t == typeid(F).hash_code())
54  new (new_v) F(std::move(*reinterpret_cast<F *>(old_v)));
55  else
56  variant_helper<Ts...>::move(old_t, old_v, new_v);
57  }
58 
59  inline static void copy(size_t old_t, const void *old_v, void *new_v)
60  {
61  if (old_t == typeid(F).hash_code())
62  new (new_v) F(*reinterpret_cast<const F *>(old_v));
63  else
64  variant_helper<Ts...>::copy(old_t, old_v, new_v);
65  }
66 };
67 
68 template <>
69 struct variant_helper<>
70 {
71  inline static void destroy(size_t id, void *data) {}
72  inline static void move(size_t old_t, void *old_v, void *new_v) {}
73  inline static void copy(size_t old_t, const void *old_v, void *new_v) {}
74 };
75 
76 template <typename... Ts>
77 struct variant
78 {
79 private:
80  static const size_t data_size = static_max<sizeof(Ts)...>::value;
81  static const size_t data_align = static_max<alignof(Ts)...>::value;
82 
83  using data_t = typename std::aligned_storage<data_size, data_align>::type;
84 
85  using helper_t = variant_helper<Ts...>;
86 
87  static inline size_t invalid_type() { return typeid(void).hash_code(); }
88 
89  size_t type_id;
90  data_t data;
91 
92 public:
94  : type_id(invalid_type())
95  {}
96 
97  variant(const variant<Ts...> &old)
98  : type_id(old.type_id)
99  {
100  helper_t::copy(old.type_id, &old.data, &data);
101  }
102 
104  : type_id(old.type_id)
105  {
106  helper_t::move(old.type_id, &old.data, &data);
107  }
108 
110  {
111  std::swap(type_id, old.type_id);
112  std::swap(data, old.data);
113 
114  return *this;
115  }
116 
117  template <typename T>
118  bool is()
119  {
120  return (type_id == typeid(T).hash_code());
121  }
122 
123  bool valid() { return (type_id != invalid_type()); }
124 
125  template <typename T, typename... Args>
126  void set(Args &&... args)
127  {
128  // First we destroy the current contents
129  helper_t::destroy(type_id, &data);
130  new (&data) T(std::forward<Args>(args)...);
131  type_id = typeid(T).hash_code();
132  }
133 
134  template <typename T>
135  T &get()
136  {
137  // It is a dynamic_cast-like behaviour
138  if (type_id == typeid(T).hash_code())
139  return *reinterpret_cast<T *>(&data);
140  else
141  throw std::bad_cast();
142  }
143 
144  ~variant() { helper_t::destroy(type_id, &data); }
145 };
146 
147 using value_variant = variant<int, double, float, bool, std::string>;
148 
149 } /* namespace ai */
150 } /* namespace flexiv */
flexiv::ai::variant
Definition: defs.hpp:248
flexiv::ai::variant::get
T & get()
Definition: variant.hpp:135
flexiv::ai::variant::operator=
variant< Ts... > & operator=(variant< Ts... > old)
Definition: variant.hpp:109
flexiv::ai::variant::set
void set(Args &&... args)
Definition: variant.hpp:126
flexiv::ai::variant_helper< F, Ts... >::copy
static void copy(size_t old_t, const void *old_v, void *new_v)
Definition: variant.hpp:59
flexiv::ai::variant::is
bool is()
Definition: variant.hpp:118
flexiv::ai::variant::~variant
~variant()
Definition: variant.hpp:144
flexiv::ai::variant::variant
variant(variant< Ts... > &&old)
Definition: variant.hpp:103
flexiv::ai::variant_helper<>::destroy
static void destroy(size_t id, void *data)
Definition: variant.hpp:71
flexiv::ai::variant_helper
Definition: defs.hpp:193
flexiv::ai::variant::variant
variant(const variant< Ts... > &old)
Definition: variant.hpp:97
flexiv::ai::variant_helper< F, Ts... >::destroy
static void destroy(size_t id, void *data)
Definition: variant.hpp:43
flexiv::ai::variant::variant
variant()
Definition: variant.hpp:93
flexiv
Definition: aidk.hpp:14
flexiv::ai::variant_helper<>::copy
static void copy(size_t old_t, const void *old_v, void *new_v)
Definition: variant.hpp:73
flexiv::ai::variant_helper<>::move
static void move(size_t old_t, void *old_v, void *new_v)
Definition: variant.hpp:72
flexiv::ai::variant_helper< F, Ts... >::move
static void move(size_t old_t, void *old_v, void *new_v)
Definition: variant.hpp:51
flexiv::ai::value_variant
variant< int, double, float, bool, std::string > value_variant
Definition: defs.hpp:319
flexiv::ai::variant::valid
bool valid()
Definition: variant.hpp:123