MSTL 1.4.0
A Modern C++ Library with extended functionality, web components, and utility libraries
载入中...
搜索中...
未找到
tuple.hpp
浏览该文件的文档.
1#ifndef MSTL_CORE_UTILITY_TUPLE_HPP__
2#define MSTL_CORE_UTILITY_TUPLE_HPP__
3
10
13
16
17template <bool Same, typename Dest, typename... Srcs>
18struct __tuple_constructible_aux : false_type {};
19
20template <typename... Dests, typename... Srcs>
21struct __tuple_constructible_aux<true, tuple<Dests...>, Srcs...> :
22 bool_constant<conjunction<is_constructible<Dests, Srcs>...>::value> {};
23
30template <typename Dest, typename... Srcs>
31struct tuple_constructible : bool_constant<
32 _INNER __tuple_constructible_aux<tuple_size<Dest>::value == sizeof...(Srcs), Dest, Srcs...>::value> {};
33
34
35template <bool Same, typename Dest, typename... Srcs>
36struct __tuple_explicitly_convertible_aux : false_type {};
37
38template <typename... Dests, typename... Srcs>
39struct __tuple_explicitly_convertible_aux<true, tuple<Dests...>, Srcs...> : bool_constant<
40 !conjunction<is_convertible<Srcs, Dests>...>::value> {};
41
48template <typename Dest, typename... Srcs>
49struct tuple_explicitly_convertible : bool_constant<
50 _INNER __tuple_explicitly_convertible_aux<tuple_size<Dest>::value == sizeof...(Srcs), Dest, Srcs...>::value> {};
51
52
60template <typename Tuple1, typename Tuple2, typename... U>
61struct tuple_perfect_forward : true_type {};
62
63template <typename Tuple1, typename Tuple2>
64struct tuple_perfect_forward<Tuple1, Tuple2> : bool_constant<!is_same<Tuple1, remove_cvref_t<Tuple2>>::value> {};
65
66template <typename T1, typename T2, typename U1, typename U2>
67struct tuple_perfect_forward<tuple<T1, T2>, U1, U2> : bool_constant<
68 disjunction<negation<is_same<remove_cvref_t<U1>, allocator_arg_tag>>,
69 is_same<remove_cvref_t<T1>, allocator_arg_tag>>::value> {};
70
71template <typename T1, typename T2, typename T3, typename U1, typename U2, typename U3>
72struct tuple_perfect_forward<tuple<T1, T2, T3>, U1, U2, U3> : bool_constant<
73 disjunction<negation<is_same<remove_cvref_t<U1>, allocator_arg_tag>>,
74 is_same<remove_cvref_t<T1>, allocator_arg_tag>>::value> {};
75
76
77template <bool Same, typename Dest, typename... Srcs>
78struct __tuple_nothrow_constructible_aux : false_type {};
79
80template <typename... Dests, typename... Srcs>
81struct __tuple_nothrow_constructible_aux<true, tuple<Dests...>, Srcs...> : bool_constant<
82 conjunction<is_nothrow_constructible<Dests, Srcs>...>::value> {};
83
90template <typename Dest, typename... Srcs>
91struct tuple_nothrow_constructible : bool_constant<
92 _INNER __tuple_nothrow_constructible_aux<tuple_size<Dest>::value == sizeof...(Srcs), Dest, Srcs...>::value> {};
93
94
95template <typename Self, typename Tuple, typename... U>
96struct __tuple_convertible_aux : true_type {};
97
98template <typename Self, typename Tuple, typename U>
99struct __tuple_convertible_aux<tuple<Self>, Tuple, U>
100 : bool_constant<!disjunction<
101 is_same<Self, U>, is_constructible<Self, Tuple>, is_convertible<Tuple, Self>>::value> {};
102
110template <typename Self, typename Tuple, typename... U>
111struct tuple_convertible : bool_constant<
112 _INNER __tuple_convertible_aux<Self, Tuple, U...>::value> {};
113
114
115template <bool Same, typename Dest, typename... Srcs>
116struct __tuple_assignable_aux : false_type {};
117
118template <typename... Dests, typename... Srcs>
119struct __tuple_assignable_aux<true, tuple<Dests...>, Srcs...> : bool_constant<
120 conjunction<is_assignable<Dests&, Srcs>...>::value> {};
121
128template <typename Dest, typename... Srcs>
129struct tuple_assignable : bool_constant<
130 _INNER __tuple_assignable_aux<tuple_size<Dest>::value == sizeof...(Srcs), Dest, Srcs...>::value> {};
131
132
133template <bool Same, typename Dest, typename... Srcs>
134struct __tuple_nothrow_assignable_aux : false_type {};
135
136template <typename... Dests, typename... Srcs>
137struct __tuple_nothrow_assignable_aux<true, tuple<Dests...>, Srcs...> : bool_constant<
138 conjunction<is_nothrow_assignable<Dests&, Srcs>...>::value> {};
139
146template <typename Dest, typename... Srcs>
147struct tuple_nothrow_assignable : bool_constant<
148 _INNER __tuple_nothrow_assignable_aux<tuple_size<Dest>::value == sizeof...(Srcs), Dest, Srcs...>::value> {};
149
152
158
164template <>
165struct tuple<> : icommon<tuple<>> {
166 constexpr tuple() noexcept = default;
167 constexpr tuple(const tuple&) noexcept = default;
168
173 template <typename Tag, enable_if_t<is_same<Tag, exact_arg_construct_tag>::value, int> = 0>
174 constexpr explicit tuple(Tag) noexcept {}
175
176 MSTL_CONSTEXPR14 tuple& operator =(const tuple&) noexcept = default;
177
182 MSTL_NODISCARD MSTL_ALWAYS_INLINE constexpr bool equal_to(const tuple&) const noexcept {
183 return true;
184 }
185
190 MSTL_NODISCARD MSTL_ALWAYS_INLINE constexpr bool less_to(const tuple&) const noexcept {
191 return false;
192 }
193
197 MSTL_ALWAYS_INLINE MSTL_CONSTEXPR14 void swap(tuple&) noexcept {}
198
203 MSTL_NODISCARD MSTL_ALWAYS_INLINE constexpr bool operator ==(const tuple& rhs) const noexcept {
204 return this->equal_to(rhs);
205 }
206
211 MSTL_NODISCARD MSTL_ALWAYS_INLINE constexpr bool operator <(const tuple& rhs) const noexcept {
212 return this->less_to(rhs);
213 }
214
219 MSTL_NODISCARD MSTL_ALWAYS_INLINE constexpr size_t to_hash() const noexcept {
220 return _CONSTANTS FNV_OFFSET_BASIS;
221 }
222};
223
224
232template <typename This, typename... Rest>
233struct tuple<This, Rest...> : private tuple<Rest...>, icommon<tuple<This, Rest...>> {
234 using this_type = This;
235 using base_type = tuple<Rest...>;
236
237private:
238 this_type data_;
239
248 template <typename Tuple, size_t... Idx>
249 static constexpr size_t __broaden_tuple(const Tuple& tup, _MSTL index_sequence<Idx...> idx) noexcept;
250
251public:
260 template <typename Tag, typename U1, typename... U2, enable_if_t<
262 constexpr tuple(Tag, U1&& this_arg, U2&&... rest_arg)
263 : base_type(exact_arg_construct_tag{}, _MSTL forward<U2>(rest_arg)...), data_(_MSTL forward<U1>(this_arg)) {}
264
273 template <typename Tag, typename Tuple, size_t... Index, enable_if_t<
275 constexpr tuple(Tag, Tuple&& tup, index_sequence<Index...> idx);
276
283 template <typename Tag, typename Tuple, enable_if_t<
285 constexpr tuple(Tag, Tuple&& tup)
287 make_index_sequence<tuple_size<remove_cvref_t<Tuple>>::value>{}) {}
288
289
290#ifdef MSTL_STANDARD_20__
295 template <typename T = This, enable_if_t<
296 conjunction_v<is_default_constructible<T>, is_default_constructible<Rest>...>, int> = 0>
297 constexpr explicit(!conjunction_v<
298 is_implicitly_default_constructible<T>, is_implicitly_default_constructible<Rest>...>)
299 tuple() noexcept(conjunction_v<
300 is_nothrow_default_constructible<T>, is_nothrow_default_constructible<Rest>...>)
301 : base_type(), data_() {}
302
309 template <typename T = This, enable_if_t<
310 _INNER tuple_constructible<tuple, const T&, const Rest&...>::value, int> = 0>
311 constexpr explicit(_INNER tuple_explicitly_convertible<tuple, const T&, const Rest&...>::value)
312 tuple(const T& this_arg, const Rest&... rest_arg) noexcept(conjunction_v<
313 is_nothrow_copy_constructible<T>, is_nothrow_copy_constructible<Rest>...>)
314 : tuple(exact_arg_construct_tag{}, this_arg, rest_arg...) {}
315
323 template <typename U1, typename... U2, enable_if_t<conjunction_v<_INNER tuple_perfect_forward<tuple, U1, U2...>,
324 _INNER tuple_constructible<tuple, U1, U2...>>, int> = 0>
325 constexpr explicit(_INNER tuple_explicitly_convertible<tuple, U1, U2...>::value)
326 tuple(U1&& this_arg, U2&&... rest_arg) noexcept(_INNER tuple_nothrow_constructible<tuple, U1, U2...>::value)
327 : tuple(exact_arg_construct_tag{}, _MSTL forward<U1>(this_arg), _MSTL forward<U2>(rest_arg)...) {}
328
334 template <typename... U, enable_if_t<conjunction_v<_INNER tuple_constructible<tuple, const U&...>,
335 _INNER tuple_convertible<tuple, const tuple<U...>&, U...>>, int> = 0>
336 constexpr explicit(_INNER tuple_explicitly_convertible<tuple, const U&...>::value)
337 tuple(const tuple<U...>& tup) noexcept(_INNER tuple_nothrow_constructible<tuple, const U&...>::value)
338 : tuple(unpack_utility_construct_tag{}, tup) {}
339
345 template <typename... U, enable_if_t<conjunction_v<_INNER tuple_constructible<tuple, U...>,
346 _INNER tuple_convertible<tuple, tuple<U...>, U...>>, int> = 0>
347 constexpr explicit(_INNER tuple_explicitly_convertible<tuple, U...>::value)
348 tuple(tuple<U...>&& tup) noexcept(_INNER tuple_nothrow_constructible<tuple, U...>::value)
349 : tuple(unpack_utility_construct_tag{}, _MSTL move(tup)) {}
350
357 template <typename T1, typename T2, enable_if_t<
358 _INNER tuple_constructible<tuple, const T1&, const T2&>::value, int> = 0>
359 constexpr explicit(_INNER tuple_explicitly_convertible<tuple, const T1&, const T2&>::value)
360 tuple(const pair<T1, T2>& pir) noexcept(_INNER tuple_nothrow_constructible<tuple, const T1&, const T2&>::value)
361 : tuple(unpack_utility_construct_tag{}, pir) {}
362
369 template <typename T1, typename T2, enable_if_t<_INNER tuple_constructible<tuple, T1, T2>::value, int> = 0>
370 constexpr explicit(_INNER tuple_explicitly_convertible<tuple, T1, T2>::value)
371 tuple(pair<T1, T2>&& pir) noexcept(_INNER tuple_nothrow_constructible<tuple, T1, T2>::value)
372 : tuple(unpack_utility_construct_tag{}, _MSTL move(pir)) {}
373#else
374 template <typename T = This, enable_if_t<
375 conjunction<is_default_constructible<T>, is_default_constructible<Rest>...>::value &&
376 !conjunction<is_implicitly_default_constructible<T>,
377 is_implicitly_default_constructible<Rest>...>::value, int> = 0>
378 explicit tuple() noexcept(conjunction<
379 is_nothrow_default_constructible<T>, is_nothrow_default_constructible<Rest>...>::value)
380 : base_type(), data_() {}
381
382 template <typename T = This, enable_if_t<
383 conjunction<is_default_constructible<T>, is_default_constructible<Rest>...>::value &&
384 conjunction<is_implicitly_default_constructible<T>,
385 is_implicitly_default_constructible<Rest>...>::value, int> = 0>
386 tuple() noexcept(conjunction<
387 is_nothrow_default_constructible<T>, is_nothrow_default_constructible<Rest>...>::value)
388 : base_type(), data_() {}
389
390 template <typename T = This, enable_if_t<_INNER tuple_constructible<tuple, const T&, const Rest&...>::value &&
391 _INNER tuple_explicitly_convertible<tuple, const T&, const Rest&...>::value, int> = 0>
392 explicit tuple(const T& this_arg, const Rest&... rest_arg) noexcept(conjunction<
393 is_nothrow_copy_constructible<T>, is_nothrow_copy_constructible<Rest>...>::value)
394 : tuple(exact_arg_construct_tag{}, this_arg, rest_arg...) {}
395
396 template <typename T = This, enable_if_t<_INNER tuple_constructible<tuple, const T&, const Rest&...>::value &&
397 !_INNER tuple_explicitly_convertible<tuple, const T&, const Rest&...>::value, int> = 0>
398 tuple(const T& this_arg, const Rest&... rest_arg) noexcept(conjunction<
399 is_nothrow_copy_constructible<T>, is_nothrow_copy_constructible<Rest>...>::value)
400 : tuple(exact_arg_construct_tag{}, this_arg, rest_arg...) {}
401
402 template <typename U1, typename... U2, enable_if_t<
403 conjunction<_INNER tuple_constructible<tuple, U1, U2...>, _INNER tuple_convertible<tuple, U1, U2...>>::value &&
404 _INNER tuple_explicitly_convertible<tuple, U1, U2...>::value, int> = 0>
405 explicit tuple(U1&& this_arg, U2&&... rest_arg) noexcept(_INNER tuple_nothrow_constructible<tuple, U1, U2...>::value)
406 : tuple(exact_arg_construct_tag{}, _MSTL forward<U1>(this_arg), _MSTL forward<U2>(rest_arg)...) {}
407
408 template <typename U1, typename... U2, enable_if_t<
409 conjunction<_INNER tuple_constructible<tuple, U1, U2...>, _INNER tuple_convertible<tuple, U1, U2...>>::value &&
410 !_INNER tuple_explicitly_convertible<tuple, U1, U2...>::value, int> = 0>
411 tuple(U1&& this_arg, U2&&... rest_arg) noexcept(_INNER tuple_nothrow_constructible<tuple, U1, U2...>::value)
412 : tuple(exact_arg_construct_tag{}, _MSTL forward<U1>(this_arg), _MSTL forward<U2>(rest_arg)...) {}
413
414 template <typename... U, enable_if_t<conjunction<_INNER tuple_constructible<tuple, const U&...>,
415 _INNER tuple_convertible<tuple, const tuple<U...>&, U...>>::value &&
416 _INNER tuple_explicitly_convertible<tuple, const U&...>::value, int> = 0>
417 explicit tuple(const tuple<U...>& tup) noexcept(_INNER tuple_nothrow_constructible<tuple, const U&...>::value)
418 : tuple(unpack_utility_construct_tag{}, tup) {}
419
420 template <typename... U, enable_if_t<conjunction<_INNER tuple_constructible<tuple, const U&...>,
421 _INNER tuple_convertible<tuple, const tuple<U...>&, U...>>::value &&
422 !_INNER tuple_explicitly_convertible<tuple, const U&...>::value, int> = 0>
423 tuple(const tuple<U...>& tup) noexcept(_INNER tuple_nothrow_constructible<tuple, const U&...>::value)
424 : tuple(unpack_utility_construct_tag{}, tup) {}
425
426 template <typename... U, enable_if_t<
427 conjunction<_INNER tuple_constructible<tuple, U...>, _INNER tuple_convertible<tuple, tuple<U...>, U...>>::value &&
428 _INNER tuple_explicitly_convertible<tuple, U...>::value, int> = 0>
429 explicit tuple(tuple<U...>&& tup) noexcept(_INNER tuple_nothrow_constructible<tuple, U...>::value)
430 : tuple(unpack_utility_construct_tag{}, _MSTL move(tup)) {}
431
432 template <typename... U, enable_if_t<
433 conjunction<_INNER tuple_constructible<tuple, U...>, _INNER tuple_convertible<tuple, tuple<U...>, U...>>::value &&
434 !_INNER tuple_explicitly_convertible<tuple, U...>::value, int> = 0>
435 tuple(tuple<U...>&& tup) noexcept(_INNER tuple_nothrow_constructible<tuple, U...>::value)
436 : tuple(unpack_utility_construct_tag{}, _MSTL move(tup)) {}
437
438 template <typename T1, typename T2, enable_if_t<_INNER tuple_constructible<tuple, const T1&, const T2&>::value &&
439 _INNER tuple_explicitly_convertible<tuple, const T1&, const T2&>::value, int> = 0>
440 explicit tuple(const pair<T1, T2>& pir) noexcept(_INNER tuple_nothrow_constructible<tuple, const T1&, const T2&>::value)
441 : tuple(unpack_utility_construct_tag{}, pir) {}
442
443 template <typename T1, typename T2, enable_if_t<_INNER tuple_constructible<tuple, const T1&, const T2&>::value &&
444 !_INNER tuple_explicitly_convertible<tuple, const T1&, const T2&>::value, int> = 0>
445 tuple(const pair<T1, T2>& pir) noexcept(_INNER tuple_nothrow_constructible<tuple, const T1&, const T2&>::value)
446 : tuple(unpack_utility_construct_tag{}, pir) {}
447
448 template <typename T1, typename T2, enable_if_t<
449 _INNER tuple_constructible<tuple, T1, T2>::value && _INNER tuple_explicitly_convertible<tuple, T1, T2>::value, int> = 0>
450 explicit tuple(pair<T1, T2>&& pir) noexcept(_INNER tuple_nothrow_constructible<tuple, T1, T2>::value)
451 : tuple(unpack_utility_construct_tag{}, _MSTL move(pir)) {}
452
453 template <typename T1, typename T2, enable_if_t<
454 _INNER tuple_constructible<tuple, T1, T2>::value && !_INNER tuple_explicitly_convertible<tuple, T1, T2>::value, int> = 0>
455 tuple(pair<T1, T2>&& pir) noexcept(_INNER tuple_nothrow_constructible<tuple, T1, T2>::value)
456 : tuple(unpack_utility_construct_tag{}, _MSTL move(pir)) {}
457#endif
458
459 tuple(const tuple&) = default;
460 tuple(tuple&&) = default;
461
468 template <typename T = This, enable_if_t<
470 MSTL_CONSTEXPR14 tuple& operator =(type_identity_t<const tuple&> tup) noexcept(conjunction<
472 data_ = tup.data_;
473 get_rest() = tup.get_rest();
474 return *this;
475 }
476
483 template <typename T = This, enable_if_t<
485 MSTL_CONSTEXPR14 tuple& operator =(type_identity_t<tuple&&> tup) noexcept(conjunction<
487 data_ = _MSTL forward<T>(tup.data_);
488 get_rest() = _MSTL forward<base_type>(tup.get_rest());
489 return *this;
490 }
491
498 template <typename... U, enable_if_t<
499 conjunction<negation<is_same<tuple, tuple<U...>>>, _INNER tuple_assignable<tuple, const U&...>>::value, int> = 0>
500 MSTL_CONSTEXPR14 tuple& operator =(const tuple<U...>& tup) noexcept(_INNER tuple_nothrow_assignable<tuple, const U&...>::value) {
501 data_ = tup.data_;
502 get_rest() = tup.get_rest();
503 return *this;
504 }
505
512 template <typename... U, enable_if_t<
513 conjunction<negation<is_same<tuple, tuple<U...>>>, _INNER tuple_assignable<tuple, U...>>::value, int> = 0>
514 MSTL_CONSTEXPR14 tuple& operator =(tuple<U...>&& tup) noexcept(_INNER tuple_nothrow_assignable<tuple, U...>::value) {
515 data_ = _MSTL forward<typename tuple<U...>::this_type>(tup.data_);
516 get_rest() = _MSTL forward<typename tuple<U...>::super>(tup.get_rest());
517 return *this;
518 }
519
527 template <typename T1, typename T2, enable_if_t<
528 _INNER tuple_assignable<tuple, const T1&, const T2&>::value, int> = 0>
529 MSTL_CONSTEXPR14 tuple& operator =(const pair<T1, T2>& pir) noexcept(
530 _INNER tuple_nothrow_assignable<tuple, const T1&, const T2&>::value) {
531 data_ = pir.first;
532 get_rest().data_ = pir.second;
533 return *this;
534 }
535
543 template <typename T1, typename T2, enable_if_t<
544 _INNER tuple_assignable<tuple, T1, T2>::value, int> = 0>
545 MSTL_CONSTEXPR14 tuple& operator =(pair<T1, T2>&& pir) noexcept(
546 _INNER tuple_nothrow_assignable<tuple, T1, T2>::value) {
547 data_ = _MSTL forward<T1>(pir.first);
548 get_rest().data_ = _MSTL forward<T2>(pir.second);
549 return *this;
550 }
551
552 tuple& operator =(const volatile tuple&) = delete;
553
558 MSTL_CONSTEXPR14 base_type& get_rest() noexcept { return *this; }
559
564 MSTL_CONSTEXPR14 const base_type& get_rest() const noexcept { return *this; }
565
572 template <typename... U>
573 MSTL_NODISCARD constexpr bool equal_to(const tuple<U...>& t) const {
574 return data_ == t.data_ && base_type::equal_to(t.get_rest());
575 }
576
583 template <typename... U>
584 MSTL_NODISCARD constexpr bool less_to(const tuple<U...>& rhs) const {
585 return data_ < rhs.data_ || (!(rhs.data_ < data_) && base_type::less_to(rhs.get_rest()));
586 }
587
588 template <size_t Index, typename... Types>
589 friend constexpr tuple_element_t<Index, Types...>& get(tuple<Types...>&) noexcept;
590 template <size_t Index, typename... Types>
591 friend constexpr const tuple_element_t<Index, Types...>& get(const tuple<Types...>&) noexcept;
592 template <size_t Index, typename... Types>
593 friend constexpr tuple_element_t<Index, Types...>&& get(tuple<Types...>&&) noexcept;
594 template <size_t Index, typename... Types>
595 friend constexpr const tuple_element_t<Index, Types...>&& get(const tuple<Types...>&&) noexcept;
596
597 template <size_t Index, typename... Types>
598 friend constexpr tuple_element_t<Index, Types...>&& pair_get_from_tuple(tuple<Types...>&&) noexcept;
599
601 MSTL_NODISCARD constexpr bool operator ==(const tuple& rhs) const noexcept {
602 return this->equal_to(rhs);
603 }
604
605 MSTL_NODISCARD constexpr bool operator <(const tuple& rhs) const noexcept {
606 return this->less_to(rhs);
607 }
608
613 MSTL_NODISCARD constexpr size_t to_hash() const noexcept {
614 return tuple::__broaden_tuple(*this, _MSTL index_sequence_for<This, Rest...>());
615 }
616
621 MSTL_CONSTEXPR14 void swap(tuple& t)
623 _MSTL swap(data_, t.data_);
624 base_type::swap(t.get_rest());
625 }
626};
627#ifdef MSTL_SUPPORT_DEDUCTION_GUIDES__
628template <typename... Types>
629tuple(Types...) -> tuple<Types...>;
630
631template <typename T1, typename T2>
632tuple(pair<T1, T2>) -> tuple<T1, T2>;
633#endif
634
635
643template <size_t Index, typename... Types>
644MSTL_NODISCARD constexpr tuple_element_t<Index, Types...>& get(tuple<Types...>& t) noexcept {
645 using T = tuple_element_t<Index, tuple<Types...>>;
646 using tuple_type = tuple_extract_base_t<Index, tuple<Types...>>;
647 return static_cast<T&>(static_cast<tuple_type&>(t).data_);
648}
649
657template <size_t Index, typename... Types>
658MSTL_NODISCARD constexpr const tuple_element_t<Index, Types...>& get(const tuple<Types...>& t) noexcept {
659 using T = tuple_element_t<Index, tuple<Types...>>;
660 using tuple_type = tuple_extract_base_t<Index, tuple<Types...>>;
661 return static_cast<const T&>(static_cast<const tuple_type&>(t).data_);
662}
663
671template <size_t Index, typename... Types>
672MSTL_NODISCARD constexpr tuple_element_t<Index, Types...>&& get(tuple<Types...>&& t) noexcept {
673 using T = tuple_element_t<Index, tuple<Types...>>;
674 using tuple_type = tuple_extract_base_t<Index, tuple<Types...>>;
675 return static_cast<T&&>(static_cast<tuple_type&&>(t).data_);
676}
677
685template <size_t Index, typename... Types>
686MSTL_NODISCARD constexpr const tuple_element_t<Index, Types...>&& get(const tuple<Types...>&& t) noexcept {
687 using T = tuple_element_t<Index, tuple<Types...>>;
688 using tuple_type = tuple_extract_base_t<Index, tuple<Types...>>;
689 return static_cast<const T&&>(static_cast<const tuple_type&&>(t).data_);
690}
691
701template <size_t Index, typename... Types>
702MSTL_NODISCARD constexpr tuple_element_t<Index, Types...>&& __pair_get_from_tuple(tuple<Types...>&& t) noexcept {
703 using T = tuple_element_t<Index, tuple<Types...>>;
704 using tuple_type = tuple_extract_base_t<Index, tuple<Types...>>;
705 return static_cast<T&&>(static_cast<tuple_type&>(t).data_);
706}
708
709template <typename This, typename... Rest>
710template <typename Tag, typename Tuple, size_t... Index, enable_if_t<
712constexpr tuple<This, Rest...>::tuple(Tag, Tuple&& tup, index_sequence<Index...> idx)
713 : tuple(exact_arg_construct_tag{}, _MSTL get<Index>(_MSTL forward<Tuple>(tup))...) {}
714
716
723template <typename... Types>
724MSTL_NODISCARD constexpr tuple<unwrap_ref_decay_t<Types>...> make_tuple(Types&&... args) {
725 using tuple_type = tuple<unwrap_ref_decay_t<Types>...>;
726 return tuple_type(_MSTL forward<Types>(args)...);
727}
728
735template <typename... Types>
736MSTL_NODISCARD constexpr tuple<Types&...> tie(Types&... args) noexcept {
737 using tuple_type = tuple<Types&...>;
738 return tuple_type(args...);
739}
740
747template <typename... Types>
748MSTL_NODISCARD constexpr tuple<Types&&...> forward_as_tuple(Types&&... args) noexcept {
749 using tuple_type = tuple<Types&&...>;
750 return tuple_type(_MSTL forward<Types>(args)...);
751}
752
755
756template <typename, typename Tuple, typename = make_index_sequence<tuple_size<remove_reference_t<Tuple>>::value>>
757struct constructible_from_tuple : false_type {};
758
759template <typename T, typename Tuple, size_t... Index>
760struct constructible_from_tuple<T, Tuple, index_sequence<Index...>> : bool_constant<
761 is_constructible<T, decltype(_MSTL get<Index>(_MSTL declval<Tuple>()))...>::value> {};
762
772template <typename T, typename Tuple, size_t... Index>
773MSTL_NODISCARD constexpr T __broaden_make_from_tuple(Tuple&& tup, index_sequence<Index...> idx)
775 return T(_MSTL get<Index>(_MSTL forward<Tuple>(tup))...);
776}
777
780
781
789template <typename T, typename Tuple, enable_if_t<_INNER constructible_from_tuple<T, Tuple>::value, int> = 0>
790MSTL_NODISCARD constexpr T make_from_tuple(Tuple&& tup)
791noexcept(noexcept(_INNER __broaden_make_from_tuple<T>(
794 return _INNER __broaden_make_from_tuple<T>(
797 );
798}
799
800
803
804template <typename, typename, typename, size_t, typename...>
805struct __tuple_cat_aux;
806
807template <typename Tuple, size_t... ElementIdx, size_t... TupleIdx, size_t NextTuple>
808struct __tuple_cat_aux<Tuple, index_sequence<ElementIdx...>, index_sequence<TupleIdx...>, NextTuple> {
809 using Ret = tuple<tuple_element_t<ElementIdx, remove_cvref_t<tuple_element_t<TupleIdx, Tuple>>>...>;
810 using ElementIdxSeq = index_sequence<ElementIdx...>;
811 using TupleIdxSeq = index_sequence<TupleIdx...>;
812};
813
814template <typename Tuple, size_t... ElementIdx, size_t... TupleIdx, size_t NextTuple, size_t... NextElement, typename... Rest>
815struct __tuple_cat_aux<Tuple, index_sequence<ElementIdx...>, index_sequence<TupleIdx...>, NextTuple, index_sequence<NextElement...>, Rest...>
816 : __tuple_cat_aux<Tuple, index_sequence<ElementIdx..., NextElement...>,
817 index_sequence<TupleIdx..., (NextTuple + 0 * NextElement)...>, NextTuple + 1, Rest...> {};
818
819template <typename... Tuples>
820using tuple_cat_bind_t = __tuple_cat_aux<tuple<Tuples&&...>, index_sequence<>, index_sequence<>, 0,
822
834template <typename Ret, size_t... ElementIdx, size_t... TupleIdx, typename Tuple>
835constexpr Ret __tuple_cat_in_turn(index_sequence<ElementIdx...> ei, index_sequence<TupleIdx...> ti, Tuple tup) {
836 return Ret{ _MSTL get<ElementIdx>(_MSTL get<TupleIdx>(_MSTL move(tup)))... };
837}
838
841
842
849template <typename... Tuples>
850MSTL_NODISCARD constexpr typename _INNER tuple_cat_bind_t<Tuples...>::Ret tuple_cat(Tuples&&... tuples) {
851 using CatImpl = _INNER tuple_cat_bind_t<Tuples...>;
852 using Ret = typename CatImpl::Ret;
853 using ElementIdxSeq = typename CatImpl::ElementIdxSeq;
854 using TupleIdxSeq = typename CatImpl::TupleIdxSeq;
855 return _INNER __tuple_cat_in_turn<Ret>(
856 ElementIdxSeq{},
857 TupleIdxSeq{},
859 );
860}
861 // Tuple
863
864#if !defined(MSTL_STANDARD_17__)
867
868template <typename Tuple, size_t Index>
869struct __broadern_tuple_hash_aux {
870 static constexpr size_t hash(const Tuple& tup) {
871 using ElementType = remove_cvref_t<tuple_element_t<Index - 1, Tuple>>;
872 return __broadern_tuple_hash_aux<Tuple, Index - 1>::hash(tup)
873 ^ _MSTL hash<ElementType>()(_MSTL get<Index - 1>(tup));
874 }
875};
876template <typename Tuple>
877struct __broadern_tuple_hash_aux<Tuple, 1> {
878 static constexpr size_t hash(const Tuple& tup) {
879 using ElementType = remove_cvref_t<tuple_element_t<0, Tuple>>;
880 return _MSTL hash<ElementType>()(_MSTL get<0>(tup));
881 }
882};
883template <typename Tuple>
884struct __broadern_tuple_hash_aux<Tuple, 0> {
885 static constexpr size_t hash(const Tuple&) {
886 return 0;
887 }
888};
889
892#endif // !MSTL_STANDARD_17__
893
894
895template <typename This, typename ... Rest>
896template <typename Tuple, size_t... Idx>
897constexpr size_t tuple<This, Rest...>::__broaden_tuple(const Tuple& tup, index_sequence<Idx...>) noexcept {
898#ifdef MSTL_STANDARD_17__
900#else
901 return _INNER __broadern_tuple_hash_aux<Tuple, sizeof...(Idx)>::hash(tup);
902#endif // MSTL_STANDARD_17__
903}
904
906
909namespace std {
910 template <typename... Types>
911 struct tuple_size<_MSTL tuple<Types...>> : _MSTL integral_constant<_MSTL size_t, sizeof...(Types)> {};
912
913 template <_MSTL size_t I, typename... Types>
914 struct tuple_element<I, _MSTL tuple<Types...>> {
915 using type = _MSTL tuple_element_t<I, _MSTL tuple<Types...>>;
916 };
917}
919
920#endif // MSTL_CORE_UTILITY_TUPLE_HPP__
MSTL_NODISCARD constexpr T && forward(remove_reference_t< T > &x) noexcept
完美转发左值
MSTL_ALWAYS_INLINE enable_if_t< is_void_v< T >, future_result_t< T > > get(future< T > &f)
通用future结果获取函数
bool operator==(const function< Res(Args...)> &f, nullptr_t null) noexcept
等于空指针比较
integer_sequence< size_t, Values... > index_sequence
索引序列
make_index_sequence< sizeof...(Types)> index_sequence_for
根据类型参数包生成索引序列
make_integer_sequence< size_t, Size > make_index_sequence
生成指定长度的索引序列
#define _MSTL
全局命名空间MSTL前缀
#define MSTL_END_INNER__
结束inner命名空间
#define _CONSTANTS
constants命名空间前缀
#define _INNER
inner命名空间前缀
#define MSTL_END_NAMESPACE__
结束全局命名空间MSTL
#define MSTL_BEGIN_NAMESPACE__
开始全局命名空间MSTL
#define MSTL_BEGIN_INNER__
开始inner命名空间
MSTL_NODISCARD constexpr bool operator<(const normal_iterator< LeftIter > &lhs, const normal_iterator< RightIter > &rhs) noexcept
小于比较运算符
uint64_t size_t
无符号大小类型
typename remove_cvref< T >::type remove_cvref_t
remove_cvref的便捷别名
typename remove_reference< T >::type remove_reference_t
remove_reference的便捷别名
constexpr Iterator2 move(Iterator1 first, Iterator1 last, Iterator2 result)
移动范围元素
void swap()=delete
删除无参数的swap重载
MSTL_NODISCARD constexpr tuple_element_t< Index, Types... > & get(tuple< Types... > &t) noexcept
获取元组中指定位置的元素引用
MSTL_NODISCARD constexpr T make_from_tuple(Tuple &&tup) noexcept(noexcept(_INNER __broaden_make_from_tuple< T >(_MSTL forward< Tuple >(tup), make_index_sequence< tuple_size< remove_reference_t< Tuple > >::value >{})))
从元组构造对象
MSTL_NODISCARD constexpr tuple< unwrap_ref_decay_t< Types >... > make_tuple(Types &&... args)
从参数创建元组
MSTL_NODISCARD constexpr tuple< Types &... > tie(Types &... args) noexcept
创建引用元组
MSTL_NODISCARD constexpr tuple< Types &&... > forward_as_tuple(Types &&... args) noexcept
创建转发引用元组
MSTL_NODISCARD constexpr _INNER tuple_cat_bind_t< Tuples... >::Ret tuple_cat(Tuples &&... tuples)
连接多个元组
bool_constant< true > true_type
表示true的类型
typename type_identity< T >::type type_identity_t
type_identity的便捷别名
bool_constant< false > false_type
表示false的类型
integral_constant< bool, Value > bool_constant
布尔常量包装器
typename enable_if< Test, T >::type enable_if_t
enable_if的便捷别名
MSTL键值对
typename tuple_element< Index, Types... >::tuple_type tuple_extract_base_t
获取tuple元素基类型的类型别名
typename tuple_element< Index, Types... >::type tuple_element_t
tuple_element的类型别名
类型集合的逻辑与操作
精确参数构造标签
哈希函数的主模板
通用接口,同时具备可比较和可哈希功能
判断类型是否可复制赋值
判断类型是否可移动赋值
判断类型是否可以使用指定参数无异常构造
判断类型是否可无异常复制赋值
判断类型是否可无异常移动赋值
判断类型是否可以与自身无异常交换
判断两个类型是否相同
逻辑非包装器
存储两个值的元组对
constexpr tuple(Tag, Tuple &&tup)
解包工具构造函数
tuple(const tuple &)=default
拷贝构造函数
tuple(tuple &&)=default
移动构造函数
tuple< Rest... > base_type
基类类型,即剩余元素的元组
MSTL_NODISCARD constexpr bool less_to(const tuple< U... > &rhs) const
比较两个元组的大小关系
This this_type
当前元素类型
MSTL_CONSTEXPR14 const base_type & get_rest() const noexcept
获取剩余元素的元组常量引用
constexpr tuple(Tag, U1 &&this_arg, U2 &&... rest_arg)
精确参数构造函数
MSTL_CONSTEXPR14 base_type & get_rest() noexcept
获取剩余元素的元组引用
MSTL_NODISCARD constexpr bool equal_to(const tuple< U... > &t) const
比较两个元组是否相等
constexpr tuple(Tag, Tuple &&tup, index_sequence< Index... > idx)
解包工具构造函数
MSTL_NODISCARD constexpr size_t to_hash() const noexcept
计算元组的哈希值
MSTL_CONSTEXPR14 void swap(tuple &t) noexcept(conjunction< is_nothrow_swappable< This >, is_nothrow_swappable< Rest >... >::value)
交换两个元组的内容
MSTL_NODISCARD MSTL_ALWAYS_INLINE constexpr bool equal_to(const tuple &) const noexcept
比较两个空元组是否相等
MSTL_NODISCARD MSTL_ALWAYS_INLINE constexpr bool less_to(const tuple &) const noexcept
比较两个空元组的大小关系
MSTL_NODISCARD MSTL_ALWAYS_INLINE constexpr size_t to_hash() const noexcept
计算空元组的哈希值
MSTL_ALWAYS_INLINE MSTL_CONSTEXPR14 void swap(tuple &) noexcept
交换操作
constexpr tuple() noexcept=default
默认构造函数
获取tuple大小的特化
解包工具构造标签