Console Library 8.0.0
A header-only library that makes C++ simple
Loading...
Searching...
No Matches
union.h
Go to the documentation of this file.
1
10
11/*
12Copyright (c) 2026 MrXie1109
13
14Permission is hereby granted, free of charge, to any person obtaining a copy
15of this software and associated documentation files (the "Software"), to deal
16in the Software without restriction, including without limitation the rights
17to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
18copies of the Software, and to permit persons to whom the Software is
19furnished to do so, subject to the following conditions:
20
21The above copyright notice and this permission notice shall be included in all
22copies or substantial portions of the Software.
23
24THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30SOFTWARE.
31*/
32
33#pragma once
34#include <cstddef>
35#include <cstring>
36#include <exception>
37#include <new>
38#include <type_traits>
39#include <utility>
40
41namespace console {
50 template <class... Ts>
51 class Union {
57 template <size_t, class...>
58 struct type_at;
59 template <class T, class... Rest>
60 struct type_at<0, T, Rest...> {
61 using type = T;
62 };
63 template <size_t N, class T, class... Rest>
64 struct type_at<N, T, Rest...> {
65 using type = typename type_at<N - 1, Rest...>::type;
66 };
67 template <size_t N, class... Types>
68 using type_at_t = typename type_at<N, Types...>::type;
69
75 template <class, class...>
76 struct type_index;
77 template <class T>
79 static constexpr size_t value = 0;
80 };
81 template <class T, class U, class... Rest>
82 struct type_index<T, U, Rest...> {
83 static constexpr bool _is_match
84 = std::is_same<typename std::decay<T>::type,
85 typename std::decay<U>::type>::value;
86 static constexpr size_t _rest_index = type_index<T, Rest...>::value;
87 static constexpr size_t value = _is_match ? 0 : _rest_index + 1;
88 };
89
93 template <size_t...>
94 struct max;
95 template <size_t N>
96 struct max<N> {
97 static constexpr size_t value = N;
98 };
99 template <size_t N, size_t... Ns>
100 struct max<N, Ns...> {
101 static constexpr size_t value
102 = N > max<Ns...>::value ? N : max<Ns...>::value;
103 };
104
108 template <class...>
109 struct has_void;
110 template <class T>
111 struct has_void<T> {
112 static const bool value
113 = std::is_same<typename std::decay<T>::type, void>::value;
114 };
115 template <class T, class... Rest>
116 struct has_void<T, Rest...> {
117 static const bool value
118 = std::is_same<typename std::decay<T>::type, void>::value
119 || has_void<Rest...>::value;
120 };
121
122 template <class...>
123 friend class Union;
124
126 alignas(max<alignof(Ts)...>::value) //
127 char data_[max<sizeof(Ts)...>::value];
128
130 size_t index_{static_cast<size_t>(-1)};
131
133 void (*deleter_)(void *) = [](void *) {};
135 void (*copier_)(void *, const void *) = [](void *, const void *) {};
137 void (*mover_)(void *, void *) = [](void *, void *) {};
139 void (*cctor_)(void *, const void *) = [](void *, const void *) {};
141 void (*mctor_)(void *, void *) = [](void *, void *) {};
142
147#define TERMINATE_FOR_EXCEPTION(...) \
148 try { \
149 __VA_ARGS__; \
150 } catch (...) { \
151 std::terminate(); \
152 }
153
159 template <class T>
160 static inline void deleter(void *ptr) {
161 static_cast<T *>(ptr)->~T();
162 }
163
170 template <class T>
171 static inline void copier(void *dest, const void *src) {
172 if (dest == src) return;
173 static_cast<T *>(dest)->~T();
174 TERMINATE_FOR_EXCEPTION(new (dest) T(*static_cast<const T *>(src)));
175 }
176
183 template <class T>
184 static void mover(void *dest, void *src) {
185 if (dest == src) return;
186 static_cast<T *>(dest)->~T();
188 new (dest) T(std::move(*static_cast<T *>(src))));
189 }
190
197 template <class T>
198 static inline void cctor(void *dest, const void *src) {
199 TERMINATE_FOR_EXCEPTION(new (dest) T(*static_cast<const T *>(src)));
200 }
201
208 template <class T>
209 static inline void mctor(void *dest, void *src) {
211 new (dest) T(std::move(*static_cast<T *>(src))));
212 }
213
222 template <size_t N, class F, class Ret>
223 typename std::enable_if<(N < sizeof...(Ts))>::type
224 _visit1(F &&f, Ret &r) {
225 if (N == index_)
226 r = f(*get<type_at_t<N, Ts...>>());
227 else
228 _visit1<N + 1>(std::forward<F>(f), r);
229 }
230
231 template <size_t N, class F, class Ret>
232 typename std::enable_if<(N == sizeof...(Ts))>::type
233 _visit1(F &&, Ret &) {}
234
243 template <size_t N, class F, class Ret>
244 typename std::enable_if<(N < sizeof...(Ts))>::type
245 _visit1(F &&f, Ret &r) const {
246 if (N == index_)
247 r = f(*get<type_at_t<N, Ts...>>());
248 else
249 _visit1<N + 1>(std::forward<F>(f), r);
250 }
251
252 template <size_t N, class F, class Ret>
253 typename std::enable_if<(N == sizeof...(Ts))>::type
254 _visit1(F &&, Ret &) const {}
255
262 template <size_t N, class F>
263 typename std::enable_if<(N < sizeof...(Ts))>::type _visit2(F &&f) {
264 if (N == index_)
266 else
267 _visit2<N + 1>(std::forward<F>(f));
268 }
269
270 template <size_t N, class F>
271 typename std::enable_if<(N == sizeof...(Ts))>::type _visit2(F &&) {}
272
279 template <size_t N, class F>
280 typename std::enable_if<(N < sizeof...(Ts))>::type
281 _visit2(F &&f) const {
282 if (N == index_)
284 else
285 _visit2<N + 1>(std::forward<F>(f));
286 }
287
288 template <size_t N, class F>
289 typename std::enable_if<(N == sizeof...(Ts))>::type
290 _visit2(F &&) const {}
291
302 template <size_t N, class Ret, class F, class... Rest>
303 typename std::enable_if<(N < sizeof...(Ts))>::type
304 _visit3(Ret &r, F &&f, Rest &&...rest) {
305 if (N == index_)
306 r = f(*get<type_at_t<N, Ts...>>());
307 else
308 _visit3<N + 1>(r, std::forward<Rest>(rest)...);
309 }
310
311 template <size_t N, class Ret, class F, class... Rest>
312 typename std::enable_if<(N == sizeof...(Ts))>::type
313 _visit3(Ret &, F &&, Rest &&...) {}
314
325 template <size_t N, class Ret, class F, class... Rest>
326 typename std::enable_if<(N < sizeof...(Ts))>::type
327 _visit3(Ret &r, F &&f, Rest &&...rest) const {
328 if (N == index_)
329 r = f(*get<type_at_t<N, Ts...>>());
330 else
331 _visit3<N + 1>(r, std::forward<Rest>(rest)...);
332 }
333
334 template <size_t N, class Ret>
335 typename std::enable_if<(N == sizeof...(Ts))>::type
336 _visit3(Ret &) const {}
337
346 template <size_t N, class F, class... Rest>
347 typename std::enable_if<(N < sizeof...(Ts))>::type
348 _visit4(F &&f, Rest &&...rest) {
349 if (N == index_)
351 else
352 _visit4<N + 1>(std::forward<Rest>(rest)...);
353 }
354
355 template <size_t N>
356 typename std::enable_if<(N == sizeof...(Ts))>::type _visit4() {}
357
366 template <size_t N, class F, class... Rest>
367 typename std::enable_if<(N < sizeof...(Ts))>::type
368 _visit4(F &&f, Rest &&...rest) const {
369 if (N == index_)
371 else
372 _visit4<N + 1>(std::forward<Rest>(rest)...);
373 }
374
375 template <size_t N>
376 typename std::enable_if<(N == sizeof...(Ts))>::type _visit4() const {}
377
378 public:
380 Union() = default;
381
384
391 template <class T,
392 class = typename std::enable_if<
393 type_index<typename std::decay<T>::type, Ts...>::value
394 != sizeof...(Ts)>::type>
395 Union(T &&value) :
397 deleter_(&deleter<typename std::decay<T>::type>),
398 copier_(&copier<typename std::decay<T>::type>),
399 mover_(&mover<typename std::decay<T>::type>), //
400 cctor_(&cctor<typename std::decay<T>::type>), //
401 mctor_(&mctor<typename std::decay<T>::type>) {
402 new (data_) typename std::decay<T>::type(std::forward<T>(value));
403 }
404
412 template <class T,
413 class = typename std::enable_if<
414 type_index<typename std::decay<T>::type, Ts...>::value
415 != sizeof...(Ts)>::type>
416 Union &operator=(T &&value) {
417 if (!empty()) deleter_(data_);
419 typename std::decay<T>::type(std::forward<T>(value)));
420 index_ = type_index<T, Ts...>::value;
426 return *this;
427 }
428
433 Union(const Union &other) :
434 index_(other.index_), deleter_(other.deleter_),
435 copier_(other.copier_), mover_(other.mover_), //
436 cctor_(other.cctor_), mctor_(other.mctor_) {
437 cctor_(data_, other.data_);
438 }
439
444 Union(Union &&other) :
445 index_(other.index_), deleter_(other.deleter_),
446 copier_(other.copier_), mover_(other.mover_), //
447 cctor_(other.cctor_), mctor_(other.mctor_) {
448 mctor_(data_, other.data_);
449 other.index_ = static_cast<size_t>(-1);
450 }
451
457 Union &operator=(const Union &other) {
458 if (this == &other) return *this;
459 deleter_ = other.deleter_;
460 copier_ = other.copier_;
461 mover_ = other.mover_;
462 cctor_ = other.cctor_;
463 mctor_ = other.mctor_;
464 if (empty())
465 cctor_(data_, other.data_);
466 else
467 copier_(data_, other.data_);
468 index_ = other.index_;
469 return *this;
470 }
471
478 if (this == &other) return *this;
479 deleter_ = other.deleter_;
480 copier_ = other.copier_;
481 mover_ = other.mover_;
482 cctor_ = other.cctor_;
483 mctor_ = other.mctor_;
484 if (empty())
485 mctor_(data_, other.data_);
486 else
487 mover_(data_, other.data_);
488 index_ = other.index_;
489 other.index_ = static_cast<size_t>(-1);
490 return *this;
491 }
492
498 template <class T>
499 T *get() {
500 return type_index<T, Ts...>::value == index_
501 ? reinterpret_cast<T *>(data_)
502 : nullptr;
503 }
504
510 template <class T>
511 const T *get() const {
512 return type_index<T, Ts...>::value == index_
513 ? reinterpret_cast<const T *>(data_)
514 : nullptr;
515 }
516
525 template <class F>
526 auto visit(F &&f) -> typename std::enable_if<
528 typename std::common_type<decltype(f(
529 std::declval<Ts &>()))...>::type>::type {
530 if (empty()) std::terminate();
531 typename std::common_type< //
532 decltype(f(std::declval<Ts &>()))...>::type result;
533 _visit1<0>(std::forward<F>(f), result);
534 return result;
535 }
536
545 template <class F>
546 auto visit(F &&f) const -> typename std::enable_if<
548 typename std::common_type<decltype(f(
549 std::declval<const Ts &>()))...>::type>::type {
550 if (empty()) std::terminate();
551 typename std::common_type< //
552 decltype(f(std::declval<const Ts &>()))...>::type result;
553 _visit1<0>(std::forward<F>(f), result);
554 return result;
555 }
556
563 template <class F>
564 auto visit(F &&f) -> typename std::enable_if<
565 has_void<decltype(f(std::declval<Ts &>()))...>::value>::type {
566 if (empty()) std::terminate();
567 _visit2<0>(std::forward<F>(f));
568 }
569
576 template <class F>
577 auto visit(F &&f) const -> typename std::enable_if<
579 if (empty()) std::terminate();
580 _visit2<0>(std::forward<F>(f));
581 }
582
592 template <class... Fs>
593 auto visit(Fs &&...fs) -> typename std::enable_if<
595 typename std::common_type<decltype(fs(
596 std::declval<Ts &>()))...>::type>::type {
597 static_assert(sizeof...(Fs) == sizeof...(Ts),
598 "Number of functors does not match number of types!");
599 if (empty()) std::terminate();
600 typename std::common_type< //
601 decltype(fs(std::declval<Ts &>()))...>::type result;
602 _visit3<0>(result, std::forward<Fs>(fs)...);
603 return result;
604 }
605
615 template <class... Fs>
616 auto visit(Fs &&...fs) const -> typename std::enable_if<
618 typename std::common_type<decltype(fs(
619 std::declval<const Ts &>()))...>::type>::type {
620 static_assert(sizeof...(Fs) == sizeof...(Ts),
621 "Number of functors does not match number of types!");
622 if (empty()) std::terminate();
623 typename std::common_type< //
624 decltype(fs(std::declval<const Ts &>()))...>::type result;
625 _visit3<0>(result, std::forward<Fs>(fs)...);
626 }
627
635 template <class... Fs>
636 auto visit(Fs &&...fs) -> typename std::enable_if<
637 has_void<decltype(fs(std::declval<Ts &>()))...>::value>::type {
638 static_assert(sizeof...(Fs) == sizeof...(Ts),
639 "Number of functors does not match number of types!");
640 if (empty()) std::terminate();
641 _visit4<0>(std::forward<Fs>(fs)...);
642 }
643
651 template <class... Fs>
652 auto
653 visit(Fs &&...fs) const -> typename std::enable_if<has_void<decltype(fs(
654 std::declval<const Ts &>()))...>::value>::type {
655 static_assert(sizeof...(Fs) == sizeof...(Ts),
656 "Number of functors does not match number of types!");
657 if (empty()) std::terminate();
658 _visit4<0>(std::forward<Fs>(fs)...);
659 }
660
665 size_t index() const { return index_; }
666
672 bool empty() const { return index_ == static_cast<size_t>(-1); }
673
674#undef TERMINATE_FOR_EXCEPTION
675 };
676
682 struct ignore_t {
688 template <class... Ts>
689 void operator()(Ts &&...) {}
690 };
691
693 static constexpr ignore_t ignore;
694}
void(*) copier_(void *, const void *)
拷贝赋值函数指针。
Definition union.h:135
std::enable_if<(N==sizeof...(Ts))>::type _visit3(Ret &) const
Definition union.h:336
auto visit(F &&f) -> typename std::enable_if< has_void< decltype(f(std::declval< Ts & >()))... >::value >::type
使用单个函数对象访问存储的值 (无返回值版本,非 const)。
Definition union.h:564
std::enable_if<(N==sizeof...(Ts))>::type _visit4()
Definition union.h:356
std::enable_if<(N==sizeof...(Ts))>::type _visit2(F &&)
Definition union.h:271
std::enable_if<(N< sizeof...(Ts))>::type _visit1(F &&f, Ret &r)
访问者模式:单函数访问器 (有返回值版本,非 const)。
Definition union.h:224
const T * get() const
按类型获取存储的值的常量指针。
Definition union.h:511
std::enable_if<(N==sizeof...(Ts))>::type _visit1(F &&, Ret &)
Definition union.h:233
bool empty() const
检查 Union 是否为空。
Definition union.h:672
void(*) deleter_(void *)
析构函数指针。
Definition union.h:133
Union & operator=(Union &&other)
移动赋值运算符。
Definition union.h:477
std::enable_if<(N< sizeof...(Ts))>::type _visit4(F &&f, Rest &&...rest) const
访问者模式:多函数访问器 (无返回值版本,const)。
Definition union.h:368
~Union()
析构函数,销毁当前存储的值 (若有)。
Definition union.h:383
auto visit(Fs &&...fs) -> typename std::enable_if< has_void< decltype(fs(std::declval< Ts & >()))... >::value >::type
使用多个函数对象访问存储的值 (无返回值版本,非 const)。
Definition union.h:636
auto visit(F &&f) -> typename std::enable_if< !has_void< decltype(f(std::declval< Ts & >()))... >::value, typename std::common_type< decltype(f(std::declval< Ts & >()))... >::type >::type
使用单个函数对象访问存储的值 (有返回值版本,非 const)。
Definition union.h:526
std::enable_if<(N< sizeof...(Ts))>::type _visit1(F &&f, Ret &r) const
访问者模式:单函数访问器 (有返回值版本,const)。
Definition union.h:245
void(*) mctor_(void *, void *)
移动构造函数指针。
Definition union.h:141
friend class Union
Definition union.h:123
Union(T &&value)
从值构造 Union。
Definition union.h:395
char data_[max< sizeof(Ts)... >::value]
原始存储区,对齐到所有类型中最严格的要求。
Definition union.h:127
auto visit(F &&f) const -> typename std::enable_if< has_void< decltype(f(std::declval< const Ts & >()))... >::value >::type
使用单个函数对象访问存储的值 (无返回值版本,const)。
Definition union.h:577
size_t index_
当前存储类型的索引,-1 表示空。
Definition union.h:130
Union(const Union &other)
拷贝构造函数。
Definition union.h:433
auto visit(Fs &&...fs) const -> typename std::enable_if< has_void< decltype(fs(std::declval< const Ts & >()))... >::value >::type
使用多个函数对象访问存储的值 (无返回值版本,const)。
Definition union.h:653
Union(Union &&other)
移动构造函数。
Definition union.h:444
std::enable_if<(N==sizeof...(Ts))>::type _visit1(F &&, Ret &) const
Definition union.h:254
std::enable_if<(N< sizeof...(Ts))>::type _visit3(Ret &r, F &&f, Rest &&...rest) const
访问者模式:多函数访问器 (有返回值版本,const)。
Definition union.h:327
auto visit(F &&f) const -> typename std::enable_if< !has_void< decltype(f(std::declval< const Ts & >()))... >::value, typename std::common_type< decltype(f(std::declval< const Ts & >()))... >::type >::type
使用单个函数对象访问存储的值 (有返回值版本,const)。
Definition union.h:546
std::enable_if<(N==sizeof...(Ts))>::type _visit4() const
Definition union.h:376
auto visit(Fs &&...fs) const -> typename std::enable_if< !has_void< decltype(fs(std::declval< const Ts & >()))... >::value, typename std::common_type< decltype(fs(std::declval< const Ts & >()))... >::type >::type
使用多个函数对象访问存储的值 (有返回值版本,const)。
Definition union.h:616
typename type_at< N, Types... >::type type_at_t
Definition union.h:68
Union()=default
默认构造函数,构造一个空的 Union (不存储任何值)。
std::enable_if<(N< sizeof...(Ts))>::type _visit3(Ret &r, F &&f, Rest &&...rest)
访问者模式:多函数访问器 (有返回值版本,非 const)。
Definition union.h:304
auto visit(Fs &&...fs) -> typename std::enable_if< !has_void< decltype(fs(std::declval< Ts & >()))... >::value, typename std::common_type< decltype(fs(std::declval< Ts & >()))... >::type >::type
使用多个函数对象访问存储的值 (有返回值版本,非 const)。
Definition union.h:593
size_t index() const
获取当前存储类型的索引。
Definition union.h:665
void(*) mover_(void *, void *)
移动赋值函数指针。
Definition union.h:137
std::enable_if<(N==sizeof...(Ts))>::type _visit2(F &&) const
Definition union.h:290
std::enable_if<(N< sizeof...(Ts))>::type _visit2(F &&f)
访问者模式:单函数访问器 (无返回值版本,非 const)。
Definition union.h:263
std::enable_if<(N< sizeof...(Ts))>::type _visit2(F &&f) const
访问者模式:单函数访问器 (无返回值版本,const)。
Definition union.h:281
static void copier(void *dest, const void *src)
类型特定的拷贝赋值函数 (就地拷贝)。
Definition union.h:171
void(*) cctor_(void *, const void *)
拷贝构造函数指针。
Definition union.h:139
static void mover(void *dest, void *src)
类型特定的移动赋值函数 (就地移动)。
Definition union.h:184
static void mctor(void *dest, void *src)
类型特定的移动构造函数 (在未初始化的内存上构造)。
Definition union.h:209
T * get()
按类型获取存储的值的指针。
Definition union.h:499
Union & operator=(const Union &other)
拷贝赋值运算符。
Definition union.h:457
static void deleter(void *ptr)
类型特定的析构函数。
Definition union.h:160
static void cctor(void *dest, const void *src)
类型特定的拷贝构造函数 (在未初始化的内存上构造)。
Definition union.h:198
std::enable_if<(N< sizeof...(Ts))>::type _visit4(F &&f, Rest &&...rest)
访问者模式:多函数访问器 (无返回值版本,非 const)。
Definition union.h:348
std::enable_if<(N==sizeof...(Ts))>::type _visit3(Ret &, F &&, Rest &&...)
Definition union.h:313
本库所有组件所在的顶层命名空间。
@ U
Definition kb.h:100
@ N
Definition kb.h:93
@ T
Definition kb.h:99
static constexpr ignore_t ignore
全局 ignore 实例,可用于忽略任意参数。
Definition union.h:693
static const bool value
Definition union.h:118
static const bool value
Definition union.h:113
检查类型列表中是否包含 void。
Definition union.h:109
static constexpr size_t value
Definition union.h:102
static constexpr size_t value
Definition union.h:97
编译期计算一组 size_t 中的最大值。
Definition union.h:94
typename type_at< N - 1, Rest... >::type type
Definition union.h:65
在类型列表中按索引获取类型。
Definition union.h:58
static constexpr bool _is_match
Definition union.h:84
static constexpr size_t value
Definition union.h:87
static constexpr size_t _rest_index
Definition union.h:86
static constexpr size_t value
Definition union.h:79
获取类型 T 在类型列表中的索引。
Definition union.h:76
忽略任意参数的函数对象类型。
Definition union.h:682
void operator()(Ts &&...)
函数调用运算符,忽略所有参数。
Definition union.h:689
#define TERMINATE_FOR_EXCEPTION(...)
宏:在异常发生时调用 std::terminate。
Definition union.h:147