Lodestar
An integrated real-time control package in C++
Any.hpp
1 //
2 // Created by Hamza El-Kebir on 12/22/21.
3 //
4 
5 #ifndef LODESTAR_ANY_HPP
6 #define LODESTAR_ANY_HPP
7 
8 #include <iostream>
9 #include <type_traits>
10 #include <array>
11 #include "DynamicDataTypes.hpp"
12 #include "TemplateTraits.hpp"
13 
14 namespace ls {
15  namespace aux {
24  template<typename... TTypes>
25  class Any {
26  template<typename T>
27  static constexpr T max(const T &a, const T &b)
28  {
29  return a > b ? a : b;
30  }
31 
32  // max_size<Ts...>::value
33  template<typename T, typename... Ts>
34  struct max_size {
35  static const size_t value = max(sizeof(T),
36  max_size<Ts...>::value);
37  };
38 
39  template<typename T>
40  struct max_size<T> {
41  static const size_t value = sizeof(T);
42  };
43 
44  size_t currentType;
45  char data[max_size<TTypes...>::value];
46 
47  // https://stackoverflow.com/a/27588263
48  template<typename T, typename... Ts>
49  struct get_index;
50 
51  template<typename T, typename... Ts>
52  struct get_index<T, T, Ts...>
53  : std::integral_constant<std::size_t, 0> {
54  static constexpr bool conclusive = true;
55  };
56 
57  template<typename T, typename Tail, typename... Ts>
58  struct get_index<T, Tail, Ts...>
59  : std::integral_constant<std::size_t,
60  1 + get_index<T, Ts...>::value> {
61  static constexpr bool conclusive = true;
62  };
63 
64  template<typename T>
65  struct get_index<T> : std::integral_constant<std::size_t, 0> {
66  static constexpr bool conclusive = false;
67  // condition is always false, but should be dependent on T
68  // static_assert(sizeof(T) == 0, "Element not found");
69  };
70  public:
71  Any()
72  : currentType(), data(),
74  {}
75 
76  DynamicDataTypes::Types tags[sizeof...(TTypes)];
77 
78  DynamicDataTypes::Types tag() const
79  {
80  return tags[currentType];
81  }
82 
83  /* This signature is required as per: https://en.cppreference.com/w/cpp/types/enable_if
84  * See section on function template equivalence.
85  */
86  template<typename TType, typename std::enable_if<get_index<TType, TTypes...>::conclusive, bool>::type = true>
87  Any(const TType &x):
88  currentType(get_index<TType, TTypes...>::value)
89  {
90  auto ptr = reinterpret_cast<const char *>(&x);
91  std::copy(ptr, ptr + sizeof(TType), data);
92  }
93 
94  template<typename TType, typename std::enable_if<!get_index<TType, TTypes...>::conclusive, bool>::type = true>
95  Any(const TType &x):
96  currentType(get_index<TType, TTypes...>::value)
97  {
98  static_assert(get_index<TType, TTypes...>::conclusive,
99  "Type not found.");
100  }
101 
102  template<typename TType, typename std::enable_if<get_index<TType, TTypes...>::conclusive, bool>::type = true>
103  const TType &operator=(const TType &x)
104  {
105  currentType = get_index<TType, TTypes...>::value;
106  auto ptr = reinterpret_cast<const char *>(&x);
107  std::copy(ptr, ptr + sizeof(TType), data);
108  return x;
109  }
110 
111  template<typename TType, typename std::enable_if<!get_index<TType, TTypes...>::conclusive, bool>::type = true>
112  const TType &operator=(const TType &x)
113  {
114  static_assert(get_index<TType, TTypes...>::conclusive,
115  "Type not found.");
116  return x;
117  }
118 
119  template<typename TType>
120  bool is() const
121  {
122  auto res = get_index<TType, TTypes...>{};
123  if (res.conclusive)
124  return currentType == res.value;
125  else
126  return false;
127  }
128 
129  template<typename TType>
130  TType &as()
131  {
132  // TODO: Use safe StatusOr<TType> instead of throwing error.
133  if (!is<TType>())
134  throw std::runtime_error("Requested type is not contained");
135 
136  return *reinterpret_cast<TType *>(data);
137  }
138 
139  template<typename TType>
140  const TType &as() const
141  {
142  // TODO: Use safe StatusOr<TType> instead of throwing error.
143  if (!is<TType>())
144  throw std::runtime_error("Requested type is not contained");
145 
146  return *reinterpret_cast<const TType *>(data);
147  }
148 
149  template<typename TType>
150  bool into(TType &x)
151  {
152  if (!is<TType>())
153  return false;
154  x = *reinterpret_cast<TType *>(data);
155  return true;
156  }
157 
158  template<typename TType>
159  bool anyConvertible()
160  {
161  return TemplateTraits::anyConvertible<TType, TTypes...>::value;
162  }
163  };
164  }
165 }
166 
167 #endif //LODESTAR_ANY_HPP
ls
Main Lodestar code.
Definition: BilinearTransformation.hpp:12
ls::aux::Any
Definition: Any.hpp:25
ls::aux::DynamicDataTypes::type_to_enum
Definition: DynamicDataTypes.hpp:28