TTKMusicPlayer  4.2.0.0
TTKMusicPlayer imitates Kugou UI, the music player uses of qmmp core library based on Qt for windows and linux
ttkvariant.h
Go to the documentation of this file.
1 #ifndef TTKVARIANT_H
2 #define TTKVARIANT_H
3 
4 /***************************************************************************
5  * This file is part of the TTK Library Module project
6  * Copyright (C) 2015 - 2025 Greedysky Studio
7 
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU Lesser General Public License as published by
10  * the Free Software Foundation; either version 3 of the License, or
11  * (at your option) any later version.
12 
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU Lesser General Public License for more details.
17 
18  * You should have received a copy of the GNU Lesser General Public License along
19  * with this program; If not, see <http://www.gnu.org/licenses/>.
20  ***************************************************************************/
21 
22 #include <typeindex>
23 #include "ttkmoduleexport.h"
24 
25 template <size_t arg, size_t... rest>
26 struct IntegerMax;
27 
28 template <size_t arg>
29 struct IntegerMax<arg> : std::integral_constant<size_t, arg> { };
30 
31 template <size_t arg1, size_t arg2, size_t... rest>
32 struct IntegerMax<arg1, arg2, rest...> : std::integral_constant<size_t, arg1 >= arg2 ? IntegerMax<arg1, rest...>::value : IntegerMax<arg2, rest...>::value> { };
33 
34 
35 template <typename... Args>
36 struct MaxAlign : std::integral_constant<int, IntegerMax<std::alignment_of<Args>::value...>::value> { };
37 
38 
39 template <typename T, typename... List>
40 struct Contains : std::true_type { };
41 
42 template <typename T, typename Head, typename... Rest>
43 struct Contains<T, Head, Rest...> : std::conditional< std::is_same<T, Head>::value, std::true_type, Contains<T, Rest...>>::type { };
44 
45 template <typename T>
46 struct Contains<T> : std::false_type { };
47 
48 
49 template <typename Type, typename... Types>
50 struct GetLeftSize;
51 
52 template <typename Type, typename First, typename... Types>
53 struct GetLeftSize<Type, First, Types...> : GetLeftSize<Type, Types...> { };
54 
55 template <typename Type, typename... Types>
56 struct GetLeftSize<Type, Type, Types...> : std::integral_constant<int, sizeof...(Types)> { };
57 
58 template <typename Type>
59 struct GetLeftSize<Type> : std::integral_constant<int, -1> { };
60 
61 
62 template <typename T, typename... Types>
63 struct Index : std::integral_constant<int, sizeof...(Types) - GetLeftSize<T, Types...>::value - 1> { };
64 
65 
66 template <typename... Args>
68 
69 template <typename T, typename... Args>
70 struct VariantHelper<T, Args...>
71 {
72  inline static void Destroy(std::type_index id, void *data)
73  {
74  if(id == std::type_index(typeid(T)))
75  {
76  //((T*) (data))->~T();
77  reinterpret_cast<T*>(data)->~T();
78  }
79  else
80  {
82  }
83  }
84 
85  inline static void move(std::type_index old_t, void *old_v, void *new_v)
86  {
87  if(old_t == std::type_index(typeid(T)))
88  {
89  new (new_v) T(std::move(*reinterpret_cast<T*>(old_v)));
90  }
91  else
92  {
93  VariantHelper<Args...>::move(old_t, old_v, new_v);
94  }
95  }
96 
97  inline static void copy(std::type_index old_t, const void *old_v, void *new_v)
98  {
99  if(old_t == std::type_index(typeid(T)))
100  {
101  new (new_v) T(*reinterpret_cast<const T*>(old_v));
102  }
103  else
104  {
105  VariantHelper<Args...>::copy(old_t, old_v, new_v);
106  }
107  }
108 };
109 
110 template <>
112 {
113  inline static void Destroy(std::type_index, void *) { }
114  inline static void move(std::type_index, void *, void *) { }
115  inline static void copy(std::type_index, const void *, void *) { }
116 };
117 
118 
122 template <typename... Types>
124 {
125  enum
126  {
127  data_size = IntegerMax<sizeof(Types)...>::value,
129  };
130 
131  typedef VariantHelper<Types...> Helper_t;
132  using data_t = typename std::aligned_storage<data_size, align_size>::type;
133 
134 public:
138  TTKVariant() noexcept
139  : m_type(typeid(void))
140  {
141 
142  }
143 
148  : m_type(other.m_type)
149  {
150  Helper_t::move(other.m_type, &other.m_data, &m_data);
151  }
152 
157  : m_type(other.m_type)
158  {
159  Helper_t::copy(other.m_type, &other.m_data, &m_data);
160  }
161 
165  template <class T,
166  class = typename std::enable_if<Contains<typename std::remove_reference<T>::type, Types...>::value>::type>
167  TTKVariant(T &&value)
168  : m_type(typeid(void))
169  {
170  Helper_t::Destroy(m_type, &m_data);
171  typedef typename std::remove_reference<T>::type U;
172  new (&m_data) U(std::forward<T>(value));
173  m_type = std::type_index(typeid(T));
174  }
175 
180  {
181  Helper_t::Destroy(m_type, &m_data);
182  }
183 
185  {
186  Helper_t::copy(other.m_type, &other.m_data, &m_data);
187  m_type = other.m_type;
188  return *this;
189  }
190 
192  {
193  Helper_t::move(other.m_type, &other.m_data, &m_data);
194  m_type = other.m_type;
195  return *this;
196  }
197 
198  bool operator==(const TTKVariant &other) const noexcept
199  {
200  return m_type == other.m_type;
201  }
202 
203  bool operator<(const TTKVariant &other) const noexcept
204  {
205  return m_type < other.m_type;
206  }
207 
208  template <typename T>
209  bool isSame() const noexcept
210  {
211  return m_type == std::type_index(typeid(T));
212  }
213 
214  bool isEmpty() const noexcept
215  {
216  return m_type == std::type_index(typeid(void));
217  }
218 
219  std::type_index type() const noexcept
220  {
221  return m_type;
222  }
223 
224  template <typename T>
225  typename std::decay<T>::type& get()
226  {
227  using U = typename std::decay<T>::type;
228  if(!isSame<U>())
229  {
230  TTK_ERROR_STREAM(typeid(U).name() << " is not defined. " << "current type is " << m_type.name());
231  throw std::bad_cast();
232  }
233  return *(U*) (&m_data);
234  }
235 
236  template <typename T>
237  int indexOf() const noexcept
238  {
239  return Index<T, Types...>::value;
240  }
241 
242 private:
244  std::type_index m_type;
245 };
246 
247 
248 // compatiblity for std variant
249 namespace std
250 {
251 #if !TTK_HAS_CXX17
252 template <typename... Types>
253 using variant = TTKVariant<Types...>;
254 #endif
255 }
256 
257 #endif // TTKVARIANT_H
static void copy(std::type_index old_t, const void *old_v, void *new_v)
Definition: ttkvariant.h:97
#define TTK_MODULE_EXPORT
#define T(v)
Definition: http_parser.c:237
TTKVariant() noexcept
Definition: ttkvariant.h:138
TTKVariant(T &&value)
Definition: ttkvariant.h:167
bool isEmpty() const noexcept
Definition: ttkvariant.h:214
typename std::aligned_storage< data_size, align_size >::type data_t
Definition: ttkvariant.h:132
bool operator==(const TTKVariant &other) const noexcept
Definition: ttkvariant.h:198
std::type_index m_type
Definition: ttkvariant.h:244
Definition: ttkcompat.h:39
int indexOf() const noexcept
Definition: ttkvariant.h:237
const char * name
Definition: http_parser.c:458
bool isSame() const noexcept
Definition: ttkvariant.h:209
static void Destroy(std::type_index id, void *data)
Definition: ttkvariant.h:72
static void Destroy(std::type_index, void *)
Definition: ttkvariant.h:113
TTKVariant(const TTKVariant< Types...> &other)
Definition: ttkvariant.h:156
static void copy(std::type_index, const void *, void *)
Definition: ttkvariant.h:115
bool operator<(const TTKVariant &other) const noexcept
Definition: ttkvariant.h:203
data_t m_data
Definition: ttkvariant.h:243
std::type_index type() const noexcept
Definition: ttkvariant.h:219
VariantHelper< Types...> Helper_t
Definition: ttkvariant.h:131
TTKVariant & operator=(TTKVariant &&other)
Definition: ttkvariant.h:191
#define const
Definition: zconf.h:233
TTKVariant & operator=(const TTKVariant &other)
Definition: ttkvariant.h:184
static void move(std::type_index, void *, void *)
Definition: ttkvariant.h:114
#define TTK_ERROR_STREAM(msg)
Definition: ttklogger.h:76
TTKVariant(TTKVariant< Types...> &&other)
Definition: ttkvariant.h:147
The class of the variant module.
Definition: ttkvariant.h:123
static void move(std::type_index old_t, void *old_v, void *new_v)
Definition: ttkvariant.h:85