You.i Engine
YiAny.h
Go to the documentation of this file.
1 // © You i Labs Inc. All rights reserved.
2 #ifndef _YI_ANY_H_
3 #define _YI_ANY_H_
4 
5 #include "framework/YiPredef.h"
6 #include "utility/YiTypeTraits.h"
7 
8 #include <type_traits>
9 
10 #ifdef YI_DEBUG
11 # include <glm/fwd.hpp>
12 # if !defined(YI_ANY_MISSING_TYPE_NAME)
13 # define YI_ANY_PROVIDE_TYPE_NAME // Convert to single define so we don't have to check both YI_ANY_MISSING_TYPE_NAME and YI_DEBUG everywhere
14 # include <typeinfo>
15 # endif
16 
17 #endif
18 
19 class CYIString;
20 class CYIUrl;
21 
22 // The internal storage size of a CYIAny for small types. The size is expanded
23 // to the nearest multiple of the pointer size.
24 //
25 // Objects this size or smaller are stored internally within the CYIAny. Objects
26 // larger than this are allocated on the heap.
27 //
28 // This define is set to the size of a glm::vec3, but expanded to avoid needing
29 // to include the glm headers.
30 #define YI_ANY_STORAGE_SIZE (sizeof(float) * 3)
31 
80 class CYIAny
81 {
82 public:
86  CYIAny();
87 
91  template<typename T, std::enable_if_t<!std::is_same<std::decay_t<T>, CYIAny>::value> * = nullptr>
92  CYIAny(T &&value);
93 
98  CYIAny(const CYIAny &other);
99 
104  CYIAny(CYIAny &&other) noexcept;
105 
113  ~CYIAny();
114 
118  CYIAny &Swap(CYIAny &other);
119 
124  CYIAny &operator=(const CYIAny &other);
125 
130  CYIAny &operator=(CYIAny &&other);
131 
140  template<typename T, std::enable_if_t<!std::is_same<std::decay_t<T>, CYIAny>::value> * = nullptr>
141  CYIAny &operator=(T &&value);
142 
149  bool Empty() const;
150 
157  void Clear();
158 
174  template<typename T>
175  bool ContainsType() const;
176 
187  bool MatchesType(const CYIAny &rOther) const;
188 
212  template<typename T>
213  std::decay_t<T> &Get();
214 
229  template<typename T>
230  const std::decay_t<T> &Get() const;
231 
242  template<typename T>
243  static size_t GetRequiredHeapMemory();
244 
245 private:
246  friend class CYIAnyTest;
247 
248  // We wrap the template functions in a struct to allow partial specialization on allocate.
249  template<typename T, bool allocate>
250  struct TypeTableFunctions
251  {
252  // Copies the given value within the CYIAny (allocating storage if necessary.)
253  static void Copy(CYIAny *pAny, const void *pOther);
254 
255  // Moves the given value within the CYIAny (allocating storage if necessary.)
256  static void Move(CYIAny *pAny, void *pOther, CYIAny *pOtherAny);
257 
258  // Gets a pointer to the value contained in this CYIAny (dereferencing to the storage as necessary.)
259  static void *GetValue(CYIAny *pAny);
260 
261  // Destroys the content of this CYIAny (de-allocating storage if necessary.)
262  static void Destroy(CYIAny *pAny);
263  };
264 
265  // The function pointer table implementing operations on a specific static type.
266  struct TypeTable
267  {
268  void (*CopyValue)(const void *pValue, CYIAny *pTo);
269  void (*CopyAny)(CYIAny *pFrom, CYIAny *pTo);
270  void (*MoveValue)(void *pValue, CYIAny *pTo);
271  void (*MoveAny)(CYIAny *pFrom, CYIAny *pTo);
272  void *(*GetValue)(CYIAny *pAny);
273  void (*Destroy)(CYIAny *pAny);
274  };
275 
276  template<typename T, std::enable_if_t<std::is_reference<T>::value || std::is_const<T>::value> * = nullptr>
277  void CopyOrMove(void *pValue);
278 
279  template<typename T, std::enable_if_t<!std::is_reference<T>::value && !std::is_const<T>::value> * = nullptr>
280  void CopyOrMove(void *pValue);
281 
282  // Gets the dynamic TypeTable for the given static type.
283  template<typename T>
284  static TypeTable *GetTypeTable();
285 
286  // The table of functions for the type stored in the CYIAny, or nullptr if
287  // the CYIAny is empty.
288  TypeTable *m_pTypeTable;
289 
290 #ifdef YI_ANY_PROVIDE_TYPE_NAME
291  // The type stored in the CYIAny, as a char array
292  const char *m_pTypeName;
293 
294  // Returns the demangled type name of the templated type. The function retains ownership of the returned pointer
295  template<typename T>
296  static const char *GetDemangledTypeName();
297 #endif
298 
299  // The storage for the contained value. If the value fits, it
300  // is allocated within the storage via placement new; otherwise
301  // a pointer to the value is stored.
302  union Storage {
303  public:
304  void *GetVoid() const;
305 
306  template<typename T>
307  T *GetCast() const;
308 
309  template<typename T>
310  void Destroy();
311 
312  private:
313  friend class CYIAnyTest;
314 
315  void *m_data[(YI_ANY_STORAGE_SIZE + sizeof(void *) - 1) / sizeof(void *)]; // round up to multiple of sizeof(void *)
316 
317 #ifdef YI_DEBUG
318  struct GlmVec3
319  {
320  float x, y, z;
321  };
322  struct GlmVec4
323  {
324  float x, y, z, w;
325  };
326 
327  bool m_bool;
328  char m_char;
329  uint8_t m_uint8;
330  int8_t m_int8;
331  uint16_t m_uint16;
332  int16_t m_int16;
333  uint32_t m_uint32;
334  int32_t m_int32;
335  uint64_t m_uint64;
336  int64_t m_int64;
337  float m_float;
338  double m_double;
339  GlmVec3 m_glmVec3;
340  GlmVec4 m_glmVec4;
341 
342  void *m_voidPointer;
343  char *m_charArray;
344  CYIString *m_string;
345  CYIUrl *m_url;
346  glm::mat3 *m_glmMat3;
347  glm::mat4 *m_glmMat4;
348 
349  public:
350  Storage();
351 #endif
352  } m_storage;
353 };
354 
362 template<typename T>
363 std::decay_t<T> &AnyCast(CYIAny &any);
364 
368 template<typename T>
369 const std::decay_t<T> &AnyCast(const CYIAny &any);
370 
378 template<typename T>
379 std::decay_t<T> *AnyCast(CYIAny *pAny);
380 
384 template<typename T>
385 const std::decay_t<T> *AnyCast(const CYIAny *pAny);
386 
389 #include "framework/internal/YiAny.inl"
390 
391 #endif // _YI_ANY_H_
bool ContainsType() const
CYIAny & operator=(const CYIAny &other)
Container class for Unicode strings. Conceptually, a CYIString object is a sequence of Unicode charac...
Definition: YiString.h:32
void Clear()
A class that holds instances of any type that is copy-constructible.
Definition: YiAny.h:80
std::decay_t< T > & Get()
#define YI_ANY_STORAGE_SIZE
Definition: YiAny.h:30
static size_t GetRequiredHeapMemory()
CYIAny & Swap(CYIAny &other)
bool MatchesType(const CYIAny &rOther) const
bool Empty() const
A class used to encapsulate an URL.
Definition: YiUrl.h:24
friend class CYIAnyTest
Definition: YiAny.h:246
std::decay_t< T > & AnyCast(CYIAny &any)