MSTL 1.4.0
A Modern C++ Library with extended functionality, web components, and utility libraries
载入中...
搜索中...
未找到
variant.hpp
浏览该文件的文档.
1#ifndef MSTL_CORE_UTILITY_VARIANT_HPP__
2#define MSTL_CORE_UTILITY_VARIANT_HPP__
3
11
14
20
27template <typename Variant, typename T>
29
30#ifdef MSTL_STANDARD_14__
35template <typename Variant, typename T>
36MSTL_INLINE17 constexpr size_t variant_index_v = variant_index<Variant, T>::value;
37#endif
38
45template <typename Variant, size_t Idx>
47
52template <typename Variant, size_t Idx>
54 // VariantTypeTraits
56
62
71template <typename... Types>
72struct variant : icommon<variant<Types...>> {
73 static_assert(sizeof...(Types) > 0, "variant must have at least one type");
74
75 static_assert(
76 !is_any_of<none_t, Types...>::value ||
77 (is_any_of<none_t, Types...>::value && is_same<get_first_para_t<Types...>, none_t>::value),
78 "if variant holds non, it should be at the first place");
79
80private:
81 size_t index_ = 0;
82
90 alignas(_MSTL max({ alignof(Types)... })) byte_t union_[_MSTL max({ sizeof(Types)... })]{};
91
92 using destruct_function = void(*)(byte_t*);
93
100 static destruct_function* destructors_table() noexcept {
101 static destruct_function function_ptrs[sizeof...(Types)] = {
102 [](byte_t* union_p) noexcept {
103 reinterpret_cast<Types*>(union_p)->~Types();
104 }...
105 };
106 return function_ptrs;
107 }
108
109 using copy_construct_function = void(*)(byte_t*, byte_t const*);
110
117 static copy_construct_function* copy_constructors_table() noexcept {
118 static copy_construct_function function_ptrs[sizeof...(Types)] = {
119 [](byte_t* union_dst, byte_t const* union_src) noexcept {
120 new (union_dst) Types(*reinterpret_cast<Types const*>(union_src));
121 }...
122 };
123 return function_ptrs;
124 }
125
126 using copy_assignment_function = void(*)(byte_t*, byte_t const*);
127
134 static copy_assignment_function* copy_assigment_functions_table() noexcept {
135 static copy_assignment_function function_ptrs[sizeof...(Types)] = {
136 [](byte_t* union_dst, byte_t const* union_src) noexcept {
137 *reinterpret_cast<Types*>(union_dst) = *reinterpret_cast<Types const*>(union_src);
138 }...
139 };
140 return function_ptrs;
141 }
142
143 using move_construct_function = void(*)(byte_t*, const byte_t*);
144
151 static move_construct_function* move_constructors_table() noexcept {
152 static move_construct_function function_ptrs[sizeof...(Types)] = {
153 [](byte_t* union_dst, const byte_t* union_src) noexcept {
154 new (union_dst) Types(_MSTL move(*reinterpret_cast<const Types*>(union_src)));
155 }...
156 };
157 return function_ptrs;
158 }
159
160 using move_assignment_function = void(*)(byte_t*, byte_t*);
161
168 static move_assignment_function* move_assigment_functions_table() noexcept {
169 static move_assignment_function function_ptrs[sizeof...(Types)] = {
170 [](byte_t* union_dst, byte_t* union_src) noexcept {
171 *reinterpret_cast<Types*>(union_dst) = _MSTL move(*reinterpret_cast<Types*>(union_src));
172 }...
173 };
174 return function_ptrs;
175 }
176
177 template <typename Lambda>
178 using const_visitor_function = common_type_t<
179 _MSTL invoke_result_t<Lambda, Types const&>...>(*)(byte_t const*, Lambda&&);
180
188 template <typename Lambda>
189 static const_visitor_function<Lambda>* const_visitors_table() noexcept {
190 static const_visitor_function<Lambda> function_ptrs[sizeof...(Types)] = {
191 [](byte_t const* union_p, Lambda&& lambda) -> _MSTL invoke_result_t<Lambda, Types const&> {
192 return _MSTL invoke(_MSTL forward<Lambda>(lambda), *reinterpret_cast<Types const*>(union_p));
193 }...
194 };
195 return function_ptrs;
196 }
197
198 template <typename Lambda>
199 using visitor_function = common_type_t<
200 _MSTL invoke_result_t<Lambda, Types&>...>(*)(byte_t*, Lambda&&);
201
209 template <typename Lambda>
210 static visitor_function<Lambda>* visitors_table() noexcept {
211 static visitor_function<Lambda> function_ptrs[sizeof...(Types)] = {
212 [](byte_t* union_p, Lambda&& lambda) -> common_type_t<_MSTL invoke_result_t<Lambda, Types&>...> {
213 return _MSTL invoke(_MSTL forward<Lambda>(lambda), *reinterpret_cast<Types*>(union_p));
214 }...
215 };
216 return function_ptrs;
217 }
218
219 template <size_t I, typename... Args, enable_if_t<
220 is_constructible_v<variant_alternative_t<variant, I>, Args...>, int> = 0>
221 constexpr bool try_construct_impl_aux_aux(Args&&... args) {
222 index_ = I;
224 return true;
225 }
226
227 template <size_t I, typename... Args, enable_if_t<
228 !is_constructible_v<variant_alternative_t<variant, I>, Args...>, int> = 0>
229 constexpr bool try_construct_impl_aux_aux(Args&&... args) {
230 return variant::try_construct_impl<I + 1>(_MSTL forward<Args>(args)...);
231 }
232
233 template <size_t I, typename... Args, enable_if_t<(I < sizeof...(Types)), int> = 0>
234 constexpr bool try_construct_impl_aux(Args&&... args) {
235 return variant::try_construct_impl_aux_aux<I>(_MSTL forward<Args>(args)...);
236 }
237
238 template <size_t I, typename... Args, enable_if_t<(I >= sizeof...(Types)), int> = 0>
239 constexpr bool try_construct_impl_aux(Args&&...) {
240 return false;
241 }
242
243 template <size_t I, typename... Args>
244 constexpr bool try_construct_impl(Args&&... args) {
245 return variant::try_construct_impl_aux<I>(_MSTL forward<Args>(args)...);
246 }
247
248 template <size_t I = 0, typename... Args>
249 constexpr bool try_construct(Args&&... args) {
250 return variant::try_construct_impl<I>(_MSTL forward<Args>(args)...);
251 }
252
253public:
259 MSTL_CONSTEXPR20 variant()
260 noexcept(is_nothrow_default_constructible_v<variant_alternative_t<variant, 0>>) {
262 }
263
271 template <typename T, enable_if_t<disjunction_v<is_same<T, Types>...>, int> = 0>
272 MSTL_CONSTEXPR20 explicit variant(T&& value)
273 noexcept(is_nothrow_move_constructible_v<T>)
274 : index_(variant_index_v<variant, T>) {
275 T* p = reinterpret_cast<T*>(union_);
276 new (p) T(_MSTL forward<T>(value));
277 }
278
285 MSTL_CONSTEXPR20 variant(const variant& x)
286 : index_(x.index_) {
287 copy_constructors_table()[index()](union_, x.union_);
288 }
289
297 MSTL_CONSTEXPR20 variant& operator =(const variant& x) {
298 if(_MSTL addressof(x) == this) return *this;
299 index_ = x.index_;
300 copy_assigment_functions_table()[index()](union_, x.union_);
301 return *this;
302 }
303
310 MSTL_CONSTEXPR20 variant(variant&& x) noexcept : index_(x.index_) {
311 move_constructors_table()[index()](union_, x.union_);
312 }
313
321 MSTL_CONSTEXPR20 variant& operator =(variant&& x) noexcept {
322 if(_MSTL addressof(x) == this) return *this;
323 index_ = x.index_;
324 move_assigment_functions_table()[index()](union_, x.union_);
325 return *this;
326 }
327
336 template <size_t Idx, typename... Args,
338 MSTL_CONSTEXPR20 explicit variant(inplace_construct_tag, Args&&... args)
339 noexcept(is_nothrow_constructible_v<variant_alternative_t<variant, Idx>, Args...>)
340 : index_(Idx) {
342 }
343
354 template <size_t Idx, typename U, typename... Args,
355 enable_if_t<is_constructible_v<variant_alternative_t<variant, Idx>, std::initializer_list<U>&, Args...>, int> = 0>
356 MSTL_CONSTEXPR20 explicit variant(inplace_construct_tag, std::initializer_list<U> ilist, Args&&... args)
357 noexcept(is_nothrow_constructible_v<variant_alternative_t<variant, Idx>, std::initializer_list<U>&, Args...>)
358 : index_(Idx) {
359 new (union_) variant_alternative_t<variant, Idx>(ilist, _MSTL forward<Args>(args)...);
360 }
361
369 template <typename... Args, enable_if_t<disjunction_v<is_constructible<Types, Args...>...>, int> = 0>
370 variant(Args&&... args) {
371 if (!variant::try_construct(_MSTL forward<Args>(args)...)) {
372 index_ = 0;
374 }
375 }
376
382 MSTL_CONSTEXPR20 ~variant() noexcept {
383 destructors_table()[index()](union_);
384 }
385
394 template <typename Lambda, enable_if_t<conjunction_v<is_invocable<Lambda, Types&>...>, int> = 0>
395 MSTL_CONSTEXPR20 common_type_t<invoke_result_t<Lambda, Types&>...> visit(Lambda&& lambda)
396 noexcept(conjunction_v<is_nothrow_invocable<Lambda, Types&>...>) {
397 return visitors_table<Lambda>()[index()](union_, _MSTL forward<Lambda>(lambda));
398 }
399
408 template <typename Lambda, enable_if_t<conjunction_v<is_invocable<Lambda, const Types&>...>, int> = 0>
409 MSTL_CONSTEXPR20 common_type_t<invoke_result_t<Lambda, const Types&>...> visit(Lambda&& lambda) const
410 noexcept(conjunction_v<is_nothrow_invocable<Lambda, const Types&>...>) {
411 return const_visitors_table<Lambda>()[index()](union_, _MSTL forward<Lambda>(lambda));
412 }
413
418 MSTL_NODISCARD MSTL_CONSTEXPR20 size_t index() const noexcept {
419 return index_;
420 }
421
427 template <typename T, enable_if_t<is_any_of_v<T, Types...>, int> = 0>
428 MSTL_NODISCARD MSTL_CONSTEXPR20 bool holds_alternative() const noexcept {
429 return variant_index_v<variant, T> == index_;
430 }
431
438 template <size_t Idx, enable_if_t<(Idx < sizeof...(Types)), int> = 0>
440 if(index_ != Idx) {
441 throw_exception(value_exception("Template index not match."));
442 }
443 return *reinterpret_cast<variant_alternative_t<variant, Idx>*>(union_);
444 }
445
452 template <typename T>
453 MSTL_CONSTEXPR20 T& get() {
455 }
456
463 template <size_t Idx, enable_if_t<(Idx < sizeof...(Types)), int> = 0>
464 MSTL_CONSTEXPR20 variant_alternative_t<variant, Idx> const& get() const {
465 if(index_ != Idx) {
466 throw_exception(value_exception("Template index not match."));
467 }
468 return *reinterpret_cast<variant_alternative_t<variant, Idx> const*>(union_);
469 }
470
477 template <typename T>
478 MSTL_CONSTEXPR20 T const& get() const {
480 }
481
487 template <size_t Idx, enable_if_t<(Idx < sizeof...(Types)), int> = 0>
488 MSTL_CONSTEXPR20 variant_alternative_t<variant, Idx>* get_if() noexcept {
489 if (index_ != Idx) return nullptr;
490 return reinterpret_cast<variant_alternative_t<variant, Idx>*>(union_);
491 }
492
498 template <typename T>
499 MSTL_CONSTEXPR20 T* get_if() noexcept {
501 }
502
508 template <size_t Idx, enable_if_t<(Idx < sizeof...(Types)), int> = 0>
509 MSTL_CONSTEXPR20 variant_alternative_t<variant, Idx> const* get_if() const noexcept {
510 if (index_ != Idx) return nullptr;
511 return reinterpret_cast<variant_alternative_t<variant, Idx> const*>(union_);
512 }
513
519 template <typename T>
520 MSTL_CONSTEXPR20 T const* get_if() const noexcept {
522 }
523
532 template <size_t Idx, typename... Args,
533 enable_if_t<(Idx < sizeof...(Types)) && is_constructible_v<variant_alternative_t<variant, Idx>, Args...>, int> = 0>
534 MSTL_CONSTEXPR20 void emplace(Args&&... args)
535 noexcept(is_nothrow_constructible_v<variant_alternative_t<variant, Idx>, Args...>) {
536 destructors_table()[index()](union_);
537 index_ = Idx;
539 }
540
549 template <typename T, typename... Args, enable_if_t<is_constructible_v<T, Args...>, int> = 0>
550 MSTL_CONSTEXPR20 void emplace(Args&&... args)
551 noexcept(is_nothrow_constructible_v<T, Args...>) {
553 }
554
561 MSTL_CONSTEXPR20 void swap(variant& x) noexcept {
562 if (_MSTL addressof(x) == this) return;
563
564 size_t this_index = index_;
565 const size_t other_index = x.index_;
566 alignas(_MSTL max({ alignof(Types)... })) byte_t temp_union[_MSTL max({ sizeof(Types)... })];
567 move_constructors_table()[this_index](reinterpret_cast<byte_t*>(temp_union), union_);
568 destructors_table()[this_index](union_);
569
570 move_constructors_table()[other_index](union_, x.union_);
571 destructors_table()[other_index](x.union_);
572 move_constructors_table()[this_index](x.union_, reinterpret_cast<byte_t*>(temp_union));
573 destructors_table()[this_index](reinterpret_cast<byte_t*>(temp_union));
574
575 index_ = other_index;
576 x.index_ = this_index;
577 }
578
586 MSTL_NODISCARD MSTL_CONSTEXPR20 bool operator ==(const variant& rhs) const {
587 if (index_ != rhs.index_) return false;
588 return this->visit([&](const auto& value) {
589 return rhs.visit([&](const auto& other_value) {
590 return value == other_value;
591 });
592 });
593 }
594
600 MSTL_NODISCARD MSTL_CONSTEXPR20 bool operator <(const variant& rhs) const {
601 if (index_ != rhs.index_) return false;
602 return this->visit([&](const auto& value) {
603 return rhs.visit([&](const auto& other_value) {
604 return value < other_value;
605 });
606 });
607 }
608
613 MSTL_NODISCARD MSTL_CONSTEXPR20 size_t to_hash() const;
614};
615
616#ifdef MSTL_SUPPORT_DEDUCTION_GUIDES__
617template <typename... Args>
618variant(Args...) -> variant<Args...>;
619#endif
620
622template <typename T, typename ...Types>
623struct variant_alternative<variant<T, Types...>, 0> {
624 using type = T;
625};
626template <typename T, typename ...Types, size_t Idx>
627struct variant_alternative<variant<T, Types...>, Idx> {
628 using type = typename variant_alternative<variant<Types...>, Idx - 1>::type;
629};
630
631template <typename T, typename ...Types>
632struct variant_index<variant<T, Types...>, T> {
633 static constexpr size_t value = 0;
634};
635template <typename T0, typename T, typename ...Types>
636struct variant_index<variant<T0, Types...>, T> {
637 static constexpr size_t value = variant_index<variant<Types...>, T>::value + 1;
638};
640
648template <size_t Idx, typename... Types>
649MSTL_CONSTEXPR20 variant_alternative_t<variant<Types...>, Idx>& get(variant<Types...>& v) {
650 using T = variant_alternative_t<variant<Types...>, Idx>;
651 using variant_type = variant<Types...>;
652 return static_cast<T&>(static_cast<variant_type&>(v).template get<Idx>());
653}
654
662template <size_t Idx, typename... Types>
663MSTL_CONSTEXPR20 const variant_alternative_t<variant<Types...>, Idx>& get(const variant<Types...>& v) {
664 using T = variant_alternative_t<variant<Types...>, Idx>;
665 using variant_type = variant<Types...>;
666 return static_cast<const T&>(static_cast<const variant_type&>(v).template get<Idx>());
667}
668
676template <size_t Idx, typename... Types>
677MSTL_CONSTEXPR20 variant_alternative_t<variant<Types...>, Idx>&& get(variant<Types...>&& v) {
678 using T = variant_alternative_t<variant<Types...>, Idx>;
679 using variant_type = variant<Types...>;
680 return static_cast<T&&>(static_cast<variant_type&&>(v).template get<Idx>());
681}
682
690template <size_t Idx, typename... Types>
691MSTL_CONSTEXPR20 const variant_alternative_t<variant<Types...>, Idx>&& get(const variant<Types...>&& v) {
692 using T = variant_alternative_t<variant<Types...>, Idx>;
693 using variant_type = variant<Types...>;
694 return static_cast<const T&&>(static_cast<const variant_type&&>(v).template get<Idx>());
695}
696
699struct __variant_elem_hasher {
700 template <typename T>
701 constexpr size_t operator ()(const T& value) const {
702 return hash<decay_t<T>>{}(value);
703 }
704};
707
708template <typename... Types>
709MSTL_CONSTEXPR20 size_t variant<Types...>::to_hash() const {
710 constexpr _INNER __variant_elem_hasher hasher{};
711 return variant::visit(hasher);
712}
713 // Variant
715
717#endif // MSTL_CORE_UTILITY_VARIANT_HPP__
MSTL_NODISCARD constexpr T * addressof(T &x) noexcept
获取对象的地址
MSTL_NODISCARD constexpr T && forward(remove_reference_t< T > &x) noexcept
完美转发左值
constexpr const T & max(const T &a, const T &b, Compare comp) noexcept(noexcept(comp(a, b)))
返回两个值中的较大者
unsigned char byte_t
字节类型,定义为无符号字符
MSTL_CONSTEXPR14 _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的便捷别名
#define _MSTL
全局命名空间MSTL前缀
#define MSTL_END_INNER__
结束inner命名空间
#define _INNER
inner命名空间前缀
#define MSTL_END_NAMESPACE__
结束全局命名空间MSTL
#define MSTL_BEGIN_NAMESPACE__
开始全局命名空间MSTL
#define MSTL_BEGIN_INNER__
开始inner命名空间
constexpr Iterator2 move(Iterator1 first, Iterator1 last, Iterator2 result)
移动范围元素
typename get_first_para< Types... >::type get_first_para_t
get_first_para的便捷别名
typename common_type< Types... >::type common_type_t
common_type的便捷别名
typename enable_if< Test, T >::type enable_if_t
enable_if的便捷别名
MSTL_CONSTEXPR20 variant_alternative_t< variant< Types... >, Idx > & get(variant< Types... > &v)
获取变体中指定索引位置的引用
MSTL_NODISCARD MSTL_CONSTEXPR20 size_t to_hash() const
计算变体的哈希值
typename variant_alternative< Variant, Idx >::type variant_alternative_t
variant_alternative的便捷别名,获取变体中指定索引位置的类型
MSTL空状态类型
通用接口,同时具备可比较和可哈希功能
原位构造标签
判断类型是否在类型集合中
判断类型是否可以使用指定参数构造
判断两个类型是否相同
空状态类型
变量处理异常
获取变体中指定索引位置的类型
获取类型在变体中的索引
变体类型主模板
MSTL_NODISCARD MSTL_CONSTEXPR20 bool holds_alternative() const noexcept
检查是否存储特定类型的值
variant(Args &&... args)
通用构造函数
MSTL_CONSTEXPR20 variant & operator=(const variant &x)
拷贝赋值运算符
MSTL_CONSTEXPR20 T * get_if() noexcept
如果存在,获取指定类型值的指针
MSTL_CONSTEXPR20 variant(inplace_construct_tag, Args &&... args) noexcept(is_nothrow_constructible_v< variant_alternative_t< variant, Idx >, Args... >)
参数列表原地构造函数
MSTL_CONSTEXPR20 variant(const variant &x)
拷贝构造函数
MSTL_CONSTEXPR20 ~variant() noexcept
析构函数
MSTL_CONSTEXPR20 common_type_t< invoke_result_t< Lambda, Types & >... > visit(Lambda &&lambda) noexcept(conjunction_v< is_nothrow_invocable< Lambda, Types & >... >)
访问变体值
MSTL_NODISCARD MSTL_CONSTEXPR20 bool operator==(const variant &rhs) const
相等比较运算符
MSTL_CONSTEXPR20 T const * get_if() const noexcept
如果存在,获取指定类型值的常量指针
MSTL_CONSTEXPR20 T const & get() const
获取指定类型值的常量引用
MSTL_CONSTEXPR20 variant() noexcept(is_nothrow_default_constructible_v< variant_alternative_t< variant, 0 > >)
默认构造函数
MSTL_NODISCARD MSTL_CONSTEXPR20 size_t index() const noexcept
获取当前存储类型的索引
MSTL_CONSTEXPR20 common_type_t< invoke_result_t< Lambda, const Types & >... > visit(Lambda &&lambda) const noexcept(conjunction_v< is_nothrow_invocable< Lambda, const Types & >... >)
常量访问变体值
MSTL_CONSTEXPR20 void emplace(Args &&... args) noexcept(is_nothrow_constructible_v< T, Args... >)
构造指定类型的新值
MSTL_CONSTEXPR20 T & get()
获取指定类型值的引用
MSTL_CONSTEXPR20 variant_alternative_t< variant, Idx > & get()
获取指定索引位置的引用
MSTL_CONSTEXPR20 void emplace(Args &&... args) noexcept(is_nothrow_constructible_v< variant_alternative_t< variant, Idx >, Args... >)
在指定位置构造新值
MSTL_CONSTEXPR20 variant_alternative_t< variant, Idx > const & get() const
获取指定索引位置的常量引用
MSTL_CONSTEXPR20 variant_alternative_t< variant, Idx > * get_if() noexcept
如果存在,获取指定索引位置的指针
MSTL_CONSTEXPR20 void swap(variant &x) noexcept
交换两个变体的内容
MSTL_CONSTEXPR20 variant_alternative_t< variant, Idx > const * get_if() const noexcept
如果存在,获取指定索引位置的常量指针
MSTL_CONSTEXPR20 variant(T &&value) noexcept(is_nothrow_move_constructible_v< T >)
从特定类型值构造
MSTL_CONSTEXPR20 variant(variant &&x) noexcept
移动构造函数
MSTL_NODISCARD MSTL_CONSTEXPR20 bool operator<(const variant &rhs) const
小于比较运算符
MSTL_CONSTEXPR20 variant(inplace_construct_tag, std::initializer_list< U > ilist, Args &&... args) noexcept(is_nothrow_constructible_v< variant_alternative_t< variant, Idx >, std::initializer_list< U > &, Args... >)
初始化列表原地构造函数