teditor  1.8.0@@fee5e94
Terminal based editor written in C++
any.hpp
Go to the documentation of this file.
1 #pragma once
2 
3 // Thanks to: https://www.ojdip.net/2013/10/implementing-a-variant-type-in-cpp/
4 
5 #include <type_traits>
6 #include <typeinfo>
7 #include <typeindex>
8 #include "utils.h"
9 
10 namespace teditor {
11 
13 template <typename... All> struct Impl;
14 
15 template <typename Head, typename... Rest>
16 struct Impl<Head, Rest...> {
17  static void destroy(const std::type_index& id, void* data) {
18  if (id == typeid(Head)) reinterpret_cast<Head*>(data)->~Head();
19  else Impl<Rest...>::destroy(id, data);
20  }
21 
22  static void move(const std::type_index& id, void* newData,
23  const void* oldData) {
24  if (id == typeid(Head))
25  new(newData) Head(std::move(*reinterpret_cast<const Head*>(oldData)));
26  else
27  Impl<Rest...>::move(id, newData, oldData);
28  }
29 
30  static void copy(const std::type_index& id, void* newData,
31  const void* oldData) {
32  if (id == typeid(Head))
33  new(newData) Head(*reinterpret_cast<const Head*>(oldData));
34  else
35  Impl<Rest...>::copy(id, newData, oldData);
36  }
37 };
38 
39 template <>
40 struct Impl<> {
41  static void destroy(const std::type_index& id, const void* data) {}
42  static void move(const std::type_index& id, void* newData,
43  const void* oldData) {}
44  static void copy(const std::type_index& id, void* newData,
45  const void* oldData) {}
46 };
48 
53 template <typename... Types>
54 struct Any {
55  private:
56  std::type_index type;
57  typename std::aligned_union<1, Types...>::type data;
58 
59  std::type_index invalidType() const { return typeid(void); }
60 
61  public:
62  Any(): type(invalidType()) {}
63 
64  Any(const Any<Types...>& old): type(old.type) {
65  Impl<Types...>::copy(type, &data, &old.data);
66  }
67 
68  Any(Any<Types...>&& old): type(old.type) {
69  Impl<Types...>::move(type, &data, &old.data);
70  }
71 
72  ~Any() { Impl<Types...>::destroy(type, &data); }
73 
74  Any<Types...>& operator=(Any<Types...>&& old) {
75  type = old.type;
76  data = old.data;
77  old.type = invalidType();
78  return *this;
79  }
80 
81  Any<Types...>& operator=(Any<Types...> old) {
82  std::swap(type, old.type);
83  std::swap(data, old.data);
84  return *this;
85  }
86 
87  template <typename T>
88  bool is() const { return type == typeid(T); }
89 
90  bool valid() const { return type != invalidType(); }
91 
92  template <typename T>
93  T& get() {
94  ASSERT(type == typeid(T), "Any::get requested-type=%s! storage-type=%s",
95  typeid(T).name(), type.name());
96  return *reinterpret_cast<T*>(&data);
97  }
98 
99  template <typename T>
100  void set(const T& in) {
101  Impl<Types...>::destroy(type, &data);
102  new(&data) T(in);
103  type = typeid(T);
104  }
105 }; // struct Any
106 
107 } // namespace teditor
teditor::Any::operator=
Any< Types... > & operator=(Any< Types... > &&old)
Definition: any.hpp:74
teditor::Impl
struct Impl ///
Definition: any.hpp:13
teditor::Any::valid
bool valid() const
Definition: any.hpp:90
teditor::Any::~Any
~Any()
Definition: any.hpp:72
teditor::Impl< Head, Rest... >::move
static void move(const std::type_index &id, void *newData, const void *oldData)
Definition: any.hpp:22
teditor::Impl<>::destroy
static void destroy(const std::type_index &id, const void *data)
Definition: any.hpp:41
teditor::Any
struct Impl ///
Definition: any.hpp:54
teditor::Any::Any
Any(Any< Types... > &&old)
Definition: any.hpp:68
teditor::Impl< Head, Rest... >::copy
static void copy(const std::type_index &id, void *newData, const void *oldData)
Definition: any.hpp:30
utils.h
teditor::Impl< Head, Rest... >::destroy
static void destroy(const std::type_index &id, void *data)
Definition: any.hpp:17
teditor::Any::is
bool is() const
Definition: any.hpp:88
teditor::Any::Any
Any(const Any< Types... > &old)
Definition: any.hpp:64
teditor::Any::operator=
Any< Types... > & operator=(Any< Types... > old)
Definition: any.hpp:81
ASSERT
#define ASSERT(check, fmt,...)
Macro to assert with runtime_error exception if the check fails.
Definition: utils.h:35
teditor::Impl<>::copy
static void copy(const std::type_index &id, void *newData, const void *oldData)
Definition: any.hpp:44
teditor::Any::Any
Any()
Definition: any.hpp:62
teditor::Any::set
void set(const T &in)
Definition: any.hpp:100
teditor::Impl<>::move
static void move(const std::type_index &id, void *newData, const void *oldData)
Definition: any.hpp:42
teditor::Any::get
T & get()
Definition: any.hpp:93
teditor
Definition: any.hpp:10