TTKMusicPlayer  4.1.3.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  //((T*) (data))->~T();
76  reinterpret_cast<T*>(data)->~T();
77  else
79  }
80 
81  inline static void move(std::type_index old_t, void *old_v, void *new_v)
82  {
83  if(old_t == std::type_index(typeid(T)))
84  new (new_v) T(std::move(*reinterpret_cast<T*>(old_v)));
85  else
86  VariantHelper<Args...>::move(old_t, old_v, new_v);
87  }
88 
89  inline static void copy(std::type_index old_t, const void *old_v, void *new_v)
90  {
91  if(old_t == std::type_index(typeid(T)))
92  new (new_v) T(*reinterpret_cast<const T*>(old_v));
93  else
94  VariantHelper<Args...>::copy(old_t, old_v, new_v);
95  }
96 };
97 
98 template <>
99 struct VariantHelper<>
100 {
101  inline static void Destroy(std::type_index, void *) {}
102  inline static void move(std::type_index, void *, void *) {}
103  inline static void copy(std::type_index, const void *, void *) {}
104 };
105 
106 
107 template <typename... Types>
109 {
110  enum
111  {
112  data_size = IntegerMax<sizeof(Types)...>::value,
114  };
115 
116  typedef VariantHelper<Types...> Helper_t;
117  using data_t = typename std::aligned_storage<data_size, align_size>::type;
118 
119 public:
124  : m_type(typeid(void))
125  {
126  }
127 
132  : m_type(other.m_type)
133  {
134  Helper_t::move(other.m_type, &other.m_data, &m_data);
135  }
136 
141  : m_type(other.m_type)
142  {
143  Helper_t::copy(other.m_type, &other.m_data, &m_data);
144  }
145 
149  template <class T,
150  class = typename std::enable_if<Contains<typename std::remove_reference<T>::type, Types...>::value>::type>
151  TTKVariant(T &&value)
152  : m_type(typeid(void))
153  {
154  Helper_t::Destroy(m_type, &m_data);
155  typedef typename std::remove_reference<T>::type U;
156  new (&m_data) U(std::forward<T>(value));
157  m_type = std::type_index(typeid(T));
158  }
159 
164  {
165  Helper_t::Destroy(m_type, &m_data);
166  }
167 
169  {
170  Helper_t::copy(other.m_type, &other.m_data, &m_data);
171  m_type = other.m_type;
172  return *this;
173  }
174 
176  {
177  Helper_t::move(other.m_type, &other.m_data, &m_data);
178  m_type = other.m_type;
179  return *this;
180  }
181 
182  bool operator==(const TTKVariant &other) const noexcept
183  {
184  return m_type == other.m_type;
185  }
186 
187  bool operator<(const TTKVariant &other) const noexcept
188  {
189  return m_type < other.m_type;
190  }
191 
192  template <typename T>
193  bool isSame() const noexcept
194  {
195  return m_type == std::type_index(typeid(T));
196  }
197 
198  bool isEmpty() const noexcept
199  {
200  return m_type == std::type_index(typeid(void));
201  }
202 
203  std::type_index type() const noexcept
204  {
205  return m_type;
206  }
207 
208  template <typename T>
209  typename std::decay<T>::type& get()
210  {
211  using U = typename std::decay<T>::type;
212  if(!isSame<U>())
213  {
214  TTK_ERROR_STREAM(typeid(U).name() << " is not defined. " << "current type is " << m_type.name());
215  throw std::bad_cast();
216  }
217  return *(U*) (&m_data);
218  }
219 
220  template<typename T>
221  int indexOf() const noexcept
222  {
223  return Index<T, Types...>::value;
224  }
225 
226 private:
228  std::type_index m_type;
229 };
230 
231 
232 namespace std
233 {
234 #if !TTK_HAS_CXX17
235 // compatiblity for std variant
236 template <typename... Types>
237 using variant = TTKVariant<Types...>;
238 #endif
239 }
240 
241 #endif // TTKVARIANT_H
static void copy(std::type_index old_t, const void *old_v, void *new_v)
Definition: ttkvariant.h:89
#define TTK_MODULE_EXPORT
#define T(v)
Definition: http_parser.c:237
TTKVariant(T &&value)
Definition: ttkvariant.h:151
bool isEmpty() const noexcept
Definition: ttkvariant.h:198
typename std::aligned_storage< data_size, align_size >::type data_t
Definition: ttkvariant.h:117
bool operator==(const TTKVariant &other) const noexcept
Definition: ttkvariant.h:182
std::type_index m_type
Definition: ttkvariant.h:228
Definition: ttkcompat.h:39
int indexOf() const noexcept
Definition: ttkvariant.h:221
const char * name
Definition: http_parser.c:458
bool isSame() const noexcept
Definition: ttkvariant.h:193
static void Destroy(std::type_index id, void *data)
Definition: ttkvariant.h:72
static void Destroy(std::type_index, void *)
Definition: ttkvariant.h:101
TTKVariant(const TTKVariant< Types...> &other)
Definition: ttkvariant.h:140
static void copy(std::type_index, const void *, void *)
Definition: ttkvariant.h:103
bool operator<(const TTKVariant &other) const noexcept
Definition: ttkvariant.h:187
data_t m_data
Definition: ttkvariant.h:227
std::type_index type() const noexcept
Definition: ttkvariant.h:203
VariantHelper< Types...> Helper_t
Definition: ttkvariant.h:116
TTKVariant & operator=(TTKVariant &&other)
Definition: ttkvariant.h:175
#define const
Definition: zconf.h:233
TTKVariant & operator=(const TTKVariant &other)
Definition: ttkvariant.h:168
static void move(std::type_index, void *, void *)
Definition: ttkvariant.h:102
#define TTK_ERROR_STREAM(msg)
Definition: ttklogger.h:70
TTKVariant(TTKVariant< Types...> &&other)
Definition: ttkvariant.h:131
static void move(std::type_index old_t, void *old_v, void *new_v)
Definition: ttkvariant.h:81