NexusForce 1.0.0
A Modern C++ Library with extended functionality, web components, and utility libraries
载入中...
搜索中...
未找到
variant.hpp
浏览该文件的文档.
1#ifndef NEFORCE_CORE_UTILITY_VARIANT_HPP__
2#define NEFORCE_CORE_UTILITY_VARIANT_HPP__
3
11
16NEFORCE_BEGIN_NAMESPACE__
17
23
30template <typename Variant, typename T>
32
33#ifdef NEFORCE_STANDARD_14
38template <typename Variant, typename T>
39NEFORCE_INLINE17 constexpr size_t variant_index_v = variant_index<Variant, T>::value;
40#endif
41
48template <typename Variant, size_t Idx>
50
55template <typename Variant, size_t Idx>
57
58
67template <typename... Types>
68struct variant : icommon<variant<Types...>> {
69 static_assert(sizeof...(Types) > 0, "variant must have at least one type");
70
71 static_assert(!is_any_of<none_t, Types...>::value ||
72 (is_any_of<none_t, Types...>::value && is_same<get_first_para_t<Types...>, none_t>::value),
73 "if variant holds none, it should be in the first place");
74
75private:
76 size_t index_ = 0;
77
85 alignas(_NEFORCE max({alignof(Types)...})) byte_t union_[_NEFORCE max({sizeof(Types)...})]{};
86
87 using destruct_function = void (*)(byte_t*);
88
95 static destruct_function* destructors_table() noexcept {
96 static destruct_function function_ptrs[sizeof...(Types)] = {
97 // NOLINTNEXTLINE(readability-non-const-parameter)
98 [](byte_t* const union_p) noexcept { reinterpret_cast<Types*>(union_p)->~Types(); }...};
99 return function_ptrs;
100 }
101
102 using copy_construct_function = void (*)(byte_t*, byte_t const*);
103
110 static copy_construct_function* copy_constructors_table() noexcept {
111 static copy_construct_function function_ptrs[sizeof...(Types)] = {
112 // NOLINTNEXTLINE(readability-non-const-parameter)
113 [](byte_t* const union_dst, byte_t const* union_src) noexcept {
114 new (union_dst) Types(*reinterpret_cast<Types const*>(union_src));
115 }...};
116 return function_ptrs;
117 }
118
119 using copy_assignment_function = void (*)(byte_t*, byte_t const*);
120
127 static copy_assignment_function* copy_assigment_functions_table() noexcept {
128 static copy_assignment_function function_ptrs[sizeof...(Types)] = {
129 [](byte_t* union_dst, byte_t const* union_src) noexcept {
130 *reinterpret_cast<Types*>(union_dst) = *reinterpret_cast<Types const*>(union_src);
131 }...};
132 return function_ptrs;
133 }
134
135 using move_construct_function = void (*)(byte_t*, const byte_t*);
136
143 static move_construct_function* move_constructors_table() noexcept {
144 static move_construct_function function_ptrs[sizeof...(Types)] = {
145 // NOLINTNEXTLINE(readability-non-const-parameter)
146 [](byte_t* const union_dst, const byte_t* union_src) noexcept {
147 new (union_dst) Types(_NEFORCE move(*reinterpret_cast<const Types*>(union_src)));
148 }...};
149 return function_ptrs;
150 }
151
152 using move_assignment_function = void (*)(byte_t*, byte_t*);
153
160 static move_assignment_function* move_assigment_functions_table() noexcept {
161 static move_assignment_function function_ptrs[sizeof...(Types)] = {
162 // NOLINTNEXTLINE(readability-non-const-parameter)
163 [](byte_t* union_dst, byte_t* const union_src) noexcept {
164 *reinterpret_cast<Types*>(union_dst) = _NEFORCE move(*reinterpret_cast<Types*>(union_src));
165 }...};
166 return function_ptrs;
167 }
168
169 template <typename Lambda>
170 using const_visitor_function = common_type_t<_NEFORCE invoke_result_t<Lambda, Types const&>...> (*)(
171 byte_t const*, Lambda&&);
172
180 template <typename Lambda>
181 static const_visitor_function<Lambda>* const_visitors_table() noexcept {
182 static const_visitor_function<Lambda> function_ptrs[sizeof...(Types)] = {
183 [](byte_t const* union_p, Lambda&& lambda) -> _NEFORCE invoke_result_t<Lambda, Types const&> {
184 return _NEFORCE invoke(_NEFORCE forward<Lambda>(lambda), *reinterpret_cast<Types const*>(union_p));
185 }...};
186 return function_ptrs;
187 }
188
189 template <typename Lambda>
190 using visitor_function =
192
200 template <typename Lambda>
201 static visitor_function<Lambda>* visitors_table() noexcept {
202 static visitor_function<Lambda> function_ptrs[sizeof...(Types)] = {
203 // NOLINTNEXTLINE(readability-non-const-parameter)
204 [](byte_t* const union_p,
205 Lambda&& lambda) -> common_type_t<_NEFORCE invoke_result_t<Lambda, Types&>...> {
206 return _NEFORCE invoke(_NEFORCE forward<Lambda>(lambda), *reinterpret_cast<Types*>(union_p));
207 }...};
208 return function_ptrs;
209 }
210
211 template <size_t I, typename... Args,
213 constexpr bool try_construct_impl_aux_aux(Args&&... args) {
214 index_ = I;
215 new (union_) variant_alternative_t<variant, I>(_NEFORCE forward<Args>(args)...);
216 return true;
217 }
218
219 template <size_t I, typename... Args,
221 constexpr bool try_construct_impl_aux_aux(Args&&... args) {
222 return variant::try_construct_impl<I + 1>(_NEFORCE forward<Args>(args)...);
223 }
224
225 template <size_t I, typename... Args, enable_if_t<(I < sizeof...(Types)), int> = 0>
226 constexpr bool try_construct_impl_aux(Args&&... args) {
227 return variant::try_construct_impl_aux_aux<I>(_NEFORCE forward<Args>(args)...);
228 }
229
230 template <size_t I, typename... Args, enable_if_t<(I >= sizeof...(Types)), int> = 0>
231 constexpr bool try_construct_impl_aux(Args&&... /*unused*/) {
232 return false;
233 }
234
235 template <size_t I, typename... Args>
236 constexpr bool try_construct_impl(Args&&... args) {
237 return variant::try_construct_impl_aux<I>(_NEFORCE forward<Args>(args)...);
238 }
239
240 template <size_t I = 0, typename... Args>
241 constexpr bool try_construct(Args&&... args) {
242 return variant::try_construct_impl<I>(_NEFORCE forward<Args>(args)...);
243 }
244
245 template <typename T, typename U>
246 static NEFORCE_CONSTEXPR20 enable_if_t<is_same_v<T, U>, bool> equal_to_impl(const T& lhs, const U& rhs) {
247 return lhs == rhs;
248 }
249 template <typename T, typename U>
250 static NEFORCE_CONSTEXPR20 enable_if_t<!is_same_v<T, U>, bool> equal_to_impl(const T& /*unused*/,
251 const U& /*unused*/) {
252 return false;
253 }
254
255 template <typename T, typename U>
256 static NEFORCE_CONSTEXPR20 enable_if_t<is_same_v<T, U>, bool> less_than_impl(const T& lhs, const U& rhs) {
257 return lhs < rhs;
258 }
259 template <typename T, typename U>
260 static NEFORCE_CONSTEXPR20 enable_if_t<!is_same_v<T, U>, bool> less_than_impl(const T& /*unused*/,
261 const U& /*unused*/) {
262 return false;
263 }
264
265public:
273 }
274
282 template <typename T, enable_if_t<disjunction_v<is_same<T, Types>...>, int> = 0>
283 NEFORCE_CONSTEXPR20 explicit variant(T&& value) noexcept(is_nothrow_move_constructible_v<T>) :
284 index_(variant_index_v<variant, T>) {
285 T* p = reinterpret_cast<T*>(union_);
286 new (p) T(_NEFORCE forward<T>(value));
287 }
288
295 NEFORCE_CONSTEXPR20 variant(const variant& other) :
296 index_(other.index_) {
297 copy_constructors_table()[index()](union_, other.union_);
298 }
299
307 NEFORCE_CONSTEXPR20 variant& operator=(const variant& other) {
308 if (_NEFORCE addressof(other) == this) {
309 return *this;
310 }
311 index_ = other.index_;
312 copy_assigment_functions_table()[index()](union_, other.union_);
313 return *this;
314 }
315
322 NEFORCE_CONSTEXPR20 variant(variant&& other) noexcept :
323 index_(other.index_) {
324 move_constructors_table()[index()](union_, other.union_);
325 }
326
334 NEFORCE_CONSTEXPR20 variant& operator=(variant&& other) noexcept {
335 if (_NEFORCE addressof(other) == this) {
336 return *this;
337 }
338 index_ = other.index_;
339 move_assigment_functions_table()[index()](union_, other.union_);
340 return *this;
341 }
342
351 template <size_t Idx, typename... Args,
353 NEFORCE_CONSTEXPR20 explicit variant(pass_size_construct_tag<Idx> /*unused*/, Args&&... args) noexcept(
355 index_(Idx) {
356 new (union_) variant_alternative_t<variant, Idx>(_NEFORCE forward<Args>(args)...);
357 }
358
369 template <size_t Idx, typename U, typename... Args,
371 int> = 0>
372 NEFORCE_CONSTEXPR20 explicit variant(
373 pass_size_construct_tag<Idx> /*unused*/, std::initializer_list<U> ilist,
375 std::initializer_list<U>&, Args...>) :
376 index_(Idx) {
377 new (union_) variant_alternative_t<variant, Idx>(ilist, _NEFORCE forward<Args>(args)...);
378 }
379
387 template <typename... Args, enable_if_t<disjunction_v<is_constructible<Types, Args...>...>, int> = 0>
388 variant(Args&&... args) {
389 if (!variant::try_construct(_NEFORCE forward<Args>(args)...)) {
390 index_ = 0;
392 }
393 }
394
400 NEFORCE_CONSTEXPR20 ~variant() noexcept { destructors_table()[index()](union_); }
401
410 template <typename Lambda, enable_if_t<conjunction_v<is_invocable<Lambda, Types&>...>, int> = 0>
413 return visitors_table<Lambda>()[index()](union_, _NEFORCE forward<Lambda>(lambda));
414 }
415
424 template <typename Lambda, enable_if_t<conjunction_v<is_invocable<Lambda, const Types&>...>, int> = 0>
425 NEFORCE_CONSTEXPR20 common_type_t<invoke_result_t<Lambda, const Types&>...> visit(Lambda&& lambda) const
427 return const_visitors_table<Lambda>()[index()](union_, _NEFORCE forward<Lambda>(lambda));
428 }
429
434 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_t index() const noexcept { return index_; }
435
441 template <typename T, enable_if_t<is_any_of_v<T, Types...>, int> = 0>
442 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 bool holds_alternative() const noexcept {
443 return variant_index_v<variant, T> == index_;
444 }
445
452 template <size_t Idx, enable_if_t<(Idx < sizeof...(Types)), int> = 0>
454 if (index_ != Idx) {
455 NEFORCE_THROW_EXCEPTION(value_exception("Template index not match."));
456 }
457 return *reinterpret_cast<variant_alternative_t<variant, Idx>*>(union_);
458 }
459
466 template <typename T>
467 NEFORCE_CONSTEXPR20 T& get() {
469 }
470
477 template <size_t Idx, enable_if_t<(Idx < sizeof...(Types)), int> = 0>
478 NEFORCE_CONSTEXPR20 variant_alternative_t<variant, Idx> const& get() const {
479 if (index_ != Idx) {
480 NEFORCE_THROW_EXCEPTION(value_exception("Template index not match."));
481 }
482 return *reinterpret_cast<variant_alternative_t<variant, Idx> const*>(union_);
483 }
484
491 template <typename T>
492 NEFORCE_CONSTEXPR20 T const& get() const {
494 }
495
501 template <size_t Idx, enable_if_t<(Idx < sizeof...(Types)), int> = 0>
502 NEFORCE_CONSTEXPR20 variant_alternative_t<variant, Idx>* get_if() noexcept {
503 if (index_ != Idx) {
504 return nullptr;
505 }
506 return reinterpret_cast<variant_alternative_t<variant, Idx>*>(union_);
507 }
508
514 template <typename T>
515 NEFORCE_CONSTEXPR20 T* get_if() noexcept {
517 }
518
524 template <size_t Idx, enable_if_t<(Idx < sizeof...(Types)), int> = 0>
525 NEFORCE_CONSTEXPR20 variant_alternative_t<variant, Idx> const* get_if() const noexcept {
526 if (index_ != Idx) {
527 return nullptr;
528 }
529 return reinterpret_cast<variant_alternative_t<variant, Idx> const*>(union_);
530 }
531
537 template <typename T>
538 NEFORCE_CONSTEXPR20 T const* get_if() const noexcept {
540 }
541
550 template <size_t Idx, typename... Args,
551 enable_if_t<(Idx < sizeof...(Types)) && is_constructible_v<variant_alternative_t<variant, Idx>, Args...>,
552 int> = 0>
553 NEFORCE_CONSTEXPR20 void
555 destructors_table()[index()](union_);
556 index_ = Idx;
557 new (union_) variant_alternative_t<variant, Idx>(_NEFORCE forward<Args>(args)...);
558 }
559
568 template <typename T, typename... Args, enable_if_t<is_constructible_v<T, Args...>, int> = 0>
569 NEFORCE_CONSTEXPR20 void emplace(Args&&... args) noexcept(is_nothrow_constructible_v<T, Args...>) {
571 }
572
579 NEFORCE_CONSTEXPR20 void swap(variant& other) noexcept {
580 if (_NEFORCE addressof(other) == this) {
581 return;
582 }
583
584 size_t this_index = index_;
585 const size_t other_index = other.index_;
586 alignas(_NEFORCE max({alignof(Types)...})) byte_t temp_union[_NEFORCE max({sizeof(Types)...})];
587 move_constructors_table()[this_index](reinterpret_cast<byte_t*>(temp_union), union_);
588 destructors_table()[this_index](union_);
589
590 move_constructors_table()[other_index](union_, other.union_);
591 destructors_table()[other_index](other.union_);
592 move_constructors_table()[this_index](other.union_, reinterpret_cast<byte_t*>(temp_union));
593 destructors_table()[this_index](reinterpret_cast<byte_t*>(temp_union));
594
595 index_ = other_index;
596 other.index_ = this_index;
597 }
598
606 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 bool equal_to(const variant& rhs) const {
607 if (index_ != rhs.index_) {
608 return false;
609 }
610 return this->visit([&](const auto& value) {
611 return rhs.visit([&](const auto& other_value) { return variant::equal_to_impl(value, other_value); });
612 });
613 }
614
620 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 bool less_than(const variant& rhs) const {
621 if (index_ != rhs.index_) {
622 return false;
623 }
624 return this->visit([&](const auto& value) {
625 return rhs.visit([&](const auto& other_value) { return variant::less_than_impl(value, other_value); });
626 });
627 }
628
633 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 size_t to_hash() const;
634};
635
636#ifdef NEFORCE_STANDARD_17
637template <typename... Args>
638variant(Args...) -> variant<Args...>;
639#endif
640
642template <typename T, typename... Types>
643struct variant_alternative<variant<T, Types...>, 0> {
644 using type = T;
645};
646template <typename T, typename... Types, size_t Idx>
647struct variant_alternative<variant<T, Types...>, Idx> {
648 using type = typename variant_alternative<variant<Types...>, Idx - 1>::type;
649};
650
651template <typename T, typename... Types>
652struct variant_index<variant<T, Types...>, T> {
653 static constexpr size_t value = 0;
654};
655template <typename T0, typename T, typename... Types>
656struct variant_index<variant<T0, Types...>, T> {
657 static constexpr size_t value = variant_index<variant<Types...>, T>::value + 1;
658};
660
668template <size_t Idx, typename... Types>
669NEFORCE_CONSTEXPR20 variant_alternative_t<variant<Types...>, Idx>& get(variant<Types...>& v) {
670 using T = variant_alternative_t<variant<Types...>, Idx>;
671 using variant_type = variant<Types...>;
672 return static_cast<T&>(static_cast<variant_type&>(v).template get<Idx>());
673}
674
682template <size_t Idx, typename... Types>
683NEFORCE_CONSTEXPR20 const variant_alternative_t<variant<Types...>, Idx>& get(const variant<Types...>& v) {
684 using T = variant_alternative_t<variant<Types...>, Idx>;
685 using variant_type = variant<Types...>;
686 return static_cast<const T&>(static_cast<const variant_type&>(v).template get<Idx>());
687}
688
696template <size_t Idx, typename... Types>
697NEFORCE_CONSTEXPR20 variant_alternative_t<variant<Types...>, Idx>&& get(variant<Types...>&& v) {
698 using T = variant_alternative_t<variant<Types...>, Idx>;
699 using variant_type = variant<Types...>;
700 return static_cast<T&&>(static_cast<variant_type&&>(v).template get<Idx>());
701}
702
710template <size_t Idx, typename... Types>
711NEFORCE_CONSTEXPR20 const variant_alternative_t<variant<Types...>, Idx>&& get(const variant<Types...>&& v) {
712 using T = variant_alternative_t<variant<Types...>, Idx>;
713 using variant_type = variant<Types...>;
714 return static_cast<const T&&>(static_cast<const variant_type&&>(v).template get<Idx>());
715}
716
717
719
720NEFORCE_BEGIN_INNER__
721struct __variant_elem_hasher {
722 template <typename T>
723 constexpr size_t operator()(const T& value) const {
724 return hash<decay_t<T>>{}(value);
725 }
726};
727NEFORCE_END_INNER__
728
729template <typename... Types>
730NEFORCE_CONSTEXPR20 size_t variant<Types...>::to_hash() const {
731 constexpr inner::__variant_elem_hasher hasher{};
732 return variant::visit(hasher);
733}
734
736 // Variant
738
739NEFORCE_END_NAMESPACE__
740#endif // NEFORCE_CORE_UTILITY_VARIANT_HPP__
比较算法
异常处理框架
constexpr T && forward(remove_reference_t< T > &x) noexcept
完美转发左值
constexpr T * addressof(T &x) noexcept
获取对象的地址
constexpr const T & max(const T &a, const T &b, Compare comp) noexcept(noexcept(comp(a, b)))
返回两个值中的较大者
unsigned char byte_t
字节类型,定义为无符号字符
constexpr inner::__invoke_result_aux< Callable, Args... >::type invoke(Callable &&f, Args &&... args) noexcept(is_nothrow_invocable< Callable, Args... >::value)
统一调用接口
typename inner::__invoke_result_aux< F, Args... >::type invoke_result_t
invoke_result的便捷别名
constexpr Iterator2 move(Iterator1 first, Iterator1 last, Iterator2 result) noexcept(noexcept(inner::__move_aux(first, last, result)))
移动范围元素
typename get_first_para< Types... >::type get_first_para_t
get_first_para的便捷别名
typename common_type< Types... >::type common_type_t
common_type的便捷别名
constexpr bool is_constructible_v
is_constructible的便捷变量模板
constexpr bool is_nothrow_default_constructible_v
is_nothrow_default_constructible的便捷变量模板
constexpr bool is_nothrow_move_constructible_v
is_nothrow_move_constructible的便捷变量模板
constexpr bool is_nothrow_constructible_v
is_nothrow_constructible的便捷变量模板
constexpr bool conjunction_v
conjunction的便捷变量模板
constexpr bool is_any_of_v
is_any_of的便捷变量模板
constexpr bool disjunction_v
disjunction的便捷变量模板
typename enable_if< Test, T >::type enable_if_t
enable_if的便捷别名
constexpr variant_alternative_t< variant< Types... >, Idx > & get(variant< Types... > &v)
获取变体中指定索引位置的引用
constexpr size_t variant_index_v
variant_index的便捷别名,获取类型在变体中的索引值
typename variant_alternative< Variant, Idx >::type variant_alternative_t
variant_alternative的便捷别名,获取变体中指定索引位置的类型
统一调用接口
空状态类型
通用接口,同时具备可比较和可哈希功能
判断类型是否在类型集合中
判断类型是否可以使用指定参数构造
判断两个类型是否相同
空状态类型
变量处理异常
获取变体中指定索引位置的类型
获取类型在变体中的索引
变体类型主模板
constexpr T const * get_if() const noexcept
如果存在,获取指定类型值的常量指针
constexpr variant(pass_size_construct_tag< Idx >, Args &&... args) noexcept(is_nothrow_constructible_v< variant_alternative_t< variant, Idx >, Args... >)
参数列表原地构造函数
constexpr variant() noexcept(is_nothrow_default_constructible_v< variant_alternative_t< variant, 0 > >)
默认构造函数
variant(Args &&... args)
通用构造函数
constexpr variant & operator=(const variant &other)
拷贝赋值运算符
constexpr variant_alternative_t< variant, Idx > const & get() const
获取指定索引位置的常量引用
constexpr void emplace(Args &&... args) noexcept(is_nothrow_constructible_v< variant_alternative_t< variant, Idx >, Args... >)
constexpr variant(variant &&other) noexcept
移动构造函数
constexpr size_t to_hash() const
计算变体的哈希值
constexpr size_t index() const noexcept
获取当前存储类型的索引
constexpr variant(pass_size_construct_tag< Idx >, std::initializer_list< U > ilist, Args &&... args) noexcept(is_nothrow_constructible_v< variant_alternative_t< variant, Idx >, std::initializer_list< U > &, Args... >)
初始化列表原地构造函数
constexpr bool less_than(const variant &rhs) const
小于比较运算符
constexpr T const & get() const
获取指定类型值的常量引用
constexpr common_type_t< invoke_result_t< Lambda, Types & >... > visit(Lambda &&lambda) noexcept(conjunction_v< is_nothrow_invocable< Lambda, Types & >... >)
访问变体值
constexpr bool equal_to(const variant &rhs) const
相等比较运算符
constexpr T * get_if() noexcept
如果存在,获取指定类型值的指针
constexpr common_type_t< invoke_result_t< Lambda, const Types & >... > visit(Lambda &&lambda) const noexcept(conjunction_v< is_nothrow_invocable< Lambda, const Types & >... >)
常量访问变体值
constexpr bool holds_alternative() const noexcept
检查是否存储特定类型的值
constexpr variant(const variant &other)
拷贝构造函数
constexpr variant(T &&value) noexcept(is_nothrow_move_constructible_v< T >)
从特定类型值构造
constexpr variant_alternative_t< variant, Idx > & get()
获取指定索引位置的引用
constexpr variant & operator=(variant &&other) noexcept
移动赋值运算符
constexpr void emplace(Args &&... args) noexcept(is_nothrow_constructible_v< T, Args... >)
构造指定类型的新值
constexpr T & get()
获取指定类型值的引用
constexpr void swap(variant &other) noexcept
交换两个变体的内容
constexpr variant_alternative_t< variant, Idx > const * get_if() const noexcept
如果存在,获取指定索引位置的常量指针
constexpr variant_alternative_t< variant, Idx > * get_if() noexcept
如果存在,获取指定索引位置的指针
constexpr ~variant() noexcept
析构函数