NexusForce 1.0.0
A Modern C++ Library with extended functionality, web components, and utility libraries
载入中...
搜索中...
未找到
tuple.hpp
浏览该文件的文档.
1#ifndef NEFORCE_CORE_UTILITY_TUPLE_HPP__
2#define NEFORCE_CORE_UTILITY_TUPLE_HPP__
3
10
12NEFORCE_BEGIN_NAMESPACE__
13
15NEFORCE_BEGIN_INNER__
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
32: bool_constant<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...>
40: bool_constant<!conjunction<is_convertible<Srcs, Dests>...>::value> {};
41
48template <typename Dest, typename... Srcs>
49struct tuple_explicitly_convertible
51 inner::__tuple_explicitly_convertible_aux<tuple_size<Dest>::value == sizeof...(Srcs), Dest, Srcs...>::value> {
52};
53
54
62template <typename Tuple1, typename Tuple2, typename... U>
63struct tuple_perfect_forward : true_type {};
64
65template <typename Tuple1, typename Tuple2>
66struct tuple_perfect_forward<Tuple1, Tuple2> : bool_constant<!is_same<Tuple1, remove_cvref_t<Tuple2>>::value> {};
67
68template <typename T1, typename T2, typename U1, typename U2>
69struct tuple_perfect_forward<tuple<T1, T2>, U1, U2>
70: bool_constant<disjunction<negation<is_same<remove_cvref_t<U1>, allocator_arg_tag>>,
71 is_same<remove_cvref_t<T1>, allocator_arg_tag>>::value> {};
72
73template <typename T1, typename T2, typename T3, typename U1, typename U2, typename U3>
74struct tuple_perfect_forward<tuple<T1, T2, T3>, U1, U2, U3>
75: bool_constant<disjunction<negation<is_same<remove_cvref_t<U1>, allocator_arg_tag>>,
76 is_same<remove_cvref_t<T1>, allocator_arg_tag>>::value> {};
77
78
79template <bool Same, typename Dest, typename... Srcs>
80struct __tuple_nothrow_constructible_aux : false_type {};
81
82template <typename... Dests, typename... Srcs>
83struct __tuple_nothrow_constructible_aux<true, tuple<Dests...>, Srcs...>
84: bool_constant<conjunction<is_nothrow_constructible<Dests, Srcs>...>::value> {};
85
92template <typename Dest, typename... Srcs>
93struct tuple_nothrow_constructible
95 inner::__tuple_nothrow_constructible_aux<tuple_size<Dest>::value == sizeof...(Srcs), Dest, Srcs...>::value> {
96};
97
98
99template <typename Self, typename Tuple, typename... U>
100struct __tuple_convertible_aux : true_type {};
101
102template <typename Self, typename Tuple, typename U>
103struct __tuple_convertible_aux<tuple<Self>, Tuple, U>
104: bool_constant<!disjunction<is_same<Self, U>, is_constructible<Self, Tuple>, is_convertible<Tuple, Self>>::value> {};
105
113template <typename Self, typename Tuple, typename... U>
114struct tuple_convertible : bool_constant<inner::__tuple_convertible_aux<Self, Tuple, U...>::value> {};
115
116
117template <bool Same, typename Dest, typename... Srcs>
118struct __tuple_assignable_aux : false_type {};
119
120template <typename... Dests, typename... Srcs>
121struct __tuple_assignable_aux<true, tuple<Dests...>, Srcs...>
122: bool_constant<conjunction<is_assignable<Dests&, Srcs>...>::value> {};
123
130template <typename Dest, typename... Srcs>
131struct tuple_assignable
132: bool_constant<inner::__tuple_assignable_aux<tuple_size<Dest>::value == sizeof...(Srcs), Dest, Srcs...>::value> {};
133
134
135template <bool Same, typename Dest, typename... Srcs>
136struct __tuple_nothrow_assignable_aux : false_type {};
137
138template <typename... Dests, typename... Srcs>
139struct __tuple_nothrow_assignable_aux<true, tuple<Dests...>, Srcs...>
140: bool_constant<conjunction<is_nothrow_assignable<Dests&, Srcs>...>::value> {};
141
148template <typename Dest, typename... Srcs>
149struct tuple_nothrow_assignable
151 inner::__tuple_nothrow_assignable_aux<tuple_size<Dest>::value == sizeof...(Srcs), Dest, Srcs...>::value> {};
152
153NEFORCE_END_INNER__
155
161
167template <>
168struct tuple<> : public icommon<tuple<>> {
169 constexpr tuple() noexcept = default;
170 constexpr tuple(const tuple&) noexcept = default;
171
176 template <typename Tag, enable_if_t<is_same<Tag, exact_arg_construct_tag>::value, int> = 0>
177 constexpr explicit tuple(Tag /*unused*/) noexcept {}
178
179 NEFORCE_CONSTEXPR14 tuple& operator=(const tuple&) noexcept = default;
180
185 NEFORCE_NODISCARD NEFORCE_ALWAYS_INLINE constexpr bool equal_to(const tuple& /*unused*/) const noexcept {
186 return true;
187 }
188
193 NEFORCE_NODISCARD NEFORCE_ALWAYS_INLINE constexpr bool less_than(const tuple& /*unused*/) const noexcept {
194 return false;
195 }
196
200 NEFORCE_ALWAYS_INLINE NEFORCE_CONSTEXPR14 void swap(tuple& /*unused*/) noexcept {}
201
206 NEFORCE_NODISCARD NEFORCE_ALWAYS_INLINE constexpr size_t to_hash() const noexcept {
207 return constants::FNV_OFFSET_BASIS;
208 }
209};
210
211
219template <typename This, typename... Rest>
220struct tuple<This, Rest...> : private tuple<Rest...>, public icommon<tuple<This, Rest...>> {
221 using this_type = This;
222 using base_type = tuple<Rest...>;
223
224private:
225 this_type data_;
226
235 template <typename Tuple, size_t... Idx>
236 static constexpr size_t __broaden_tuple(const Tuple& tup, index_sequence<Idx...> idx) noexcept;
237
238 template <typename... Args>
239 friend struct tuple;
240
241public:
250 template <typename Tag, typename U1, typename... U2,
252 constexpr tuple(Tag /*unused*/, U1&& this_arg, U2&&... rest_arg) :
253 base_type(exact_arg_construct_tag{}, _NEFORCE forward<U2>(rest_arg)...),
254 data_(_NEFORCE forward<U1>(this_arg)) {}
255
264 template <typename Tag, typename Tuple, size_t... Index,
266 constexpr tuple(Tag /*unused*/, Tuple&& tup, index_sequence<Index...> idx);
267
274 template <typename Tag, typename Tuple, enable_if_t<is_same<Tag, unpack_utility_construct_tag>::value, int> = 0>
275 constexpr tuple(Tag /*unused*/, Tuple&& tup) :
276 tuple(unpack_utility_construct_tag{}, _NEFORCE forward<Tuple>(tup),
277 make_index_sequence<tuple_size<remove_cvref_t<Tuple>>::value>{}) {}
278
279
280#ifdef NEFORCE_STANDARD_20
285 template <typename T = This,
286 enable_if_t<conjunction_v<is_default_constructible<T>, is_default_constructible<Rest>...>, int> = 0>
293
300 template <typename T = This,
301 enable_if_t<inner::tuple_constructible<tuple, const T&, const Rest&...>::value, int> = 0>
302 constexpr explicit(inner::tuple_explicitly_convertible<tuple, const T&, const Rest&...>::value)
303 tuple(const T& this_arg, const Rest&... rest_arg) noexcept(
305 tuple(exact_arg_construct_tag{}, this_arg, rest_arg...) {}
306
314 template <typename U1, typename... U2,
315 enable_if_t<conjunction_v<inner::tuple_perfect_forward<tuple, U1, U2...>,
316 inner::tuple_constructible<tuple, U1, U2...>>,
317 int> = 0>
318 constexpr explicit(inner::tuple_explicitly_convertible<tuple, U1, U2...>::value)
319 tuple(U1&& this_arg,
320 U2&&... rest_arg) noexcept(inner::tuple_nothrow_constructible<tuple, U1, U2...>::value) :
321 tuple(exact_arg_construct_tag{}, _NEFORCE forward<U1>(this_arg), _NEFORCE forward<U2>(rest_arg)...) {}
322
328 template <typename... U, enable_if_t<conjunction_v<inner::tuple_constructible<tuple, const U&...>,
329 inner::tuple_convertible<tuple, const tuple<U...>&, U...>>,
330 int> = 0>
331 constexpr explicit(inner::tuple_explicitly_convertible<tuple, const U&...>::value)
332 tuple(const tuple<U...>& tup) noexcept(inner::tuple_nothrow_constructible<tuple, const U&...>::value) :
333 tuple(unpack_utility_construct_tag{}, tup) {}
334
340 template <typename... U, enable_if_t<conjunction_v<inner::tuple_constructible<tuple, U...>,
341 inner::tuple_convertible<tuple, tuple<U...>, U...>>,
342 int> = 0>
343 constexpr explicit(inner::tuple_explicitly_convertible<tuple, U...>::value)
344 tuple(tuple<U...>&& tup) noexcept(inner::tuple_nothrow_constructible<tuple, U...>::value) :
345 tuple(unpack_utility_construct_tag{}, _NEFORCE move(tup)) {}
346
353 template <typename T1, typename T2,
355 constexpr explicit(inner::tuple_explicitly_convertible<tuple, const T1&, const T2&>::value) tuple(
356 const pair<T1, T2>& pir) noexcept(inner::tuple_nothrow_constructible<tuple, const T1&, const T2&>::value) :
357 tuple(unpack_utility_construct_tag{}, pir) {}
358
365 template <typename T1, typename T2, enable_if_t<inner::tuple_constructible<tuple, T1, T2>::value, int> = 0>
366 constexpr explicit(inner::tuple_explicitly_convertible<tuple, T1, T2>::value)
367 tuple(pair<T1, T2>&& pir) noexcept(inner::tuple_nothrow_constructible<tuple, T1, T2>::value) :
368 tuple(unpack_utility_construct_tag{}, _NEFORCE move(pir)) {}
369#else
370 template <typename T = This,
374 int> = 0>
375 explicit tuple() noexcept(
377 base_type(),
378 data_() {}
379
380 template <typename T = This,
381 enable_if_t<conjunction<is_default_constructible<T>, is_default_constructible<Rest>...>::value &&
382 conjunction<is_implicitly_default_constructible<T>,
383 is_implicitly_default_constructible<Rest>...>::value,
384 int> = 0>
385 tuple() noexcept(
386 conjunction<is_nothrow_default_constructible<T>, is_nothrow_default_constructible<Rest>...>::value) :
387 base_type(),
388 data_() {}
389
390 template <typename T = This,
391 enable_if_t<inner::tuple_constructible<tuple, const T&, const Rest&...>::value &&
392 inner::tuple_explicitly_convertible<tuple, const T&, const Rest&...>::value,
393 int> = 0>
394 explicit tuple(const T& this_arg, const Rest&... rest_arg) noexcept(
395 conjunction<is_nothrow_copy_constructible<T>, is_nothrow_copy_constructible<Rest>...>::value) :
396 tuple(exact_arg_construct_tag{}, this_arg, rest_arg...) {}
397
398 template <typename T = This,
399 enable_if_t<inner::tuple_constructible<tuple, const T&, const Rest&...>::value &&
400 !inner::tuple_explicitly_convertible<tuple, const T&, const Rest&...>::value,
401 int> = 0>
402 tuple(const T& this_arg, const Rest&... rest_arg) noexcept(
403 conjunction<is_nothrow_copy_constructible<T>, is_nothrow_copy_constructible<Rest>...>::value) :
404 tuple(exact_arg_construct_tag{}, this_arg, rest_arg...) {}
405
406 template <typename U1, typename... U2,
407 enable_if_t<conjunction<inner::tuple_constructible<tuple, U1, U2...>,
408 inner::tuple_convertible<tuple, U1, U2...>>::value &&
409 inner::tuple_explicitly_convertible<tuple, U1, U2...>::value,
410 int> = 0>
411 explicit tuple(U1&& this_arg,
412 U2&&... rest_arg) noexcept(inner::tuple_nothrow_constructible<tuple, U1, U2...>::value) :
413 tuple(exact_arg_construct_tag{}, _NEFORCE forward<U1>(this_arg), _NEFORCE forward<U2>(rest_arg)...) {}
414
415 template <typename U1, typename... U2,
416 enable_if_t<conjunction<inner::tuple_constructible<tuple, U1, U2...>,
417 inner::tuple_convertible<tuple, U1, U2...>>::value &&
418 !inner::tuple_explicitly_convertible<tuple, U1, U2...>::value,
419 int> = 0>
420 tuple(U1&& this_arg, U2&&... rest_arg) noexcept(inner::tuple_nothrow_constructible<tuple, U1, U2...>::value) :
421 tuple(exact_arg_construct_tag{}, _NEFORCE forward<U1>(this_arg), _NEFORCE forward<U2>(rest_arg)...) {}
422
423 template <typename... U,
424 enable_if_t<conjunction<inner::tuple_constructible<tuple, const U&...>,
425 inner::tuple_convertible<tuple, const tuple<U...>&, U...>>::value &&
426 inner::tuple_explicitly_convertible<tuple, const U&...>::value,
427 int> = 0>
428 explicit tuple(const tuple<U...>& tup) noexcept(inner::tuple_nothrow_constructible<tuple, const U&...>::value) :
429 tuple(unpack_utility_construct_tag{}, tup) {}
430
431 template <typename... U,
432 enable_if_t<conjunction<inner::tuple_constructible<tuple, const U&...>,
433 inner::tuple_convertible<tuple, const tuple<U...>&, U...>>::value &&
434 !inner::tuple_explicitly_convertible<tuple, const U&...>::value,
435 int> = 0>
436 tuple(const tuple<U...>& tup) noexcept(inner::tuple_nothrow_constructible<tuple, const U&...>::value) :
437 tuple(unpack_utility_construct_tag{}, tup) {}
438
439 template <typename... U, enable_if_t<conjunction<inner::tuple_constructible<tuple, U...>,
440 inner::tuple_convertible<tuple, tuple<U...>, U...>>::value &&
441 inner::tuple_explicitly_convertible<tuple, U...>::value,
442 int> = 0>
443 explicit tuple(tuple<U...>&& tup) noexcept(inner::tuple_nothrow_constructible<tuple, U...>::value) :
444 tuple(unpack_utility_construct_tag{}, _NEFORCE move(tup)) {}
445
446 template <typename... U, enable_if_t<conjunction<inner::tuple_constructible<tuple, U...>,
447 inner::tuple_convertible<tuple, tuple<U...>, U...>>::value &&
448 !inner::tuple_explicitly_convertible<tuple, U...>::value,
449 int> = 0>
450 tuple(tuple<U...>&& tup) noexcept(inner::tuple_nothrow_constructible<tuple, U...>::value) :
451 tuple(unpack_utility_construct_tag{}, _NEFORCE move(tup)) {}
452
453 template <typename T1, typename T2,
454 enable_if_t<inner::tuple_constructible<tuple, const T1&, const T2&>::value &&
455 inner::tuple_explicitly_convertible<tuple, const T1&, const T2&>::value,
456 int> = 0>
457 explicit tuple(const pair<T1, T2>& pir) noexcept(
458 inner::tuple_nothrow_constructible<tuple, const T1&, const T2&>::value) :
459 tuple(unpack_utility_construct_tag{}, pir) {}
460
461 template <typename T1, typename T2,
462 enable_if_t<inner::tuple_constructible<tuple, const T1&, const T2&>::value &&
463 !inner::tuple_explicitly_convertible<tuple, const T1&, const T2&>::value,
464 int> = 0>
465 tuple(const pair<T1, T2>& pir) noexcept(inner::tuple_nothrow_constructible<tuple, const T1&, const T2&>::value) :
466 tuple(unpack_utility_construct_tag{}, pir) {}
467
468 template <typename T1, typename T2,
469 enable_if_t<inner::tuple_constructible<tuple, T1, T2>::value &&
470 inner::tuple_explicitly_convertible<tuple, T1, T2>::value,
471 int> = 0>
472 explicit tuple(pair<T1, T2>&& pir) noexcept(inner::tuple_nothrow_constructible<tuple, T1, T2>::value) :
473 tuple(unpack_utility_construct_tag{}, _NEFORCE move(pir)) {}
474
475 template <typename T1, typename T2,
476 enable_if_t<inner::tuple_constructible<tuple, T1, T2>::value &&
477 !inner::tuple_explicitly_convertible<tuple, T1, T2>::value,
478 int> = 0>
479 tuple(pair<T1, T2>&& pir) noexcept(inner::tuple_nothrow_constructible<tuple, T1, T2>::value) :
480 tuple(unpack_utility_construct_tag{}, _NEFORCE move(pir)) {}
481#endif
482
483 tuple(const tuple&) = default;
484 tuple(tuple&&) = default;
485
492 template <typename T = This,
494 NEFORCE_CONSTEXPR14 tuple& operator=(type_identity_t<const tuple&> tup) noexcept(
496 data_ = tup.data_;
497 get_rest() = tup.get_rest();
498 return *this;
499 }
500
507 template <typename T = This,
509 NEFORCE_CONSTEXPR14 tuple& operator=(type_identity_t<tuple&&> tup) noexcept(
511 data_ = _NEFORCE forward<T>(tup.data_);
512 get_rest() = _NEFORCE forward<base_type>(tup.get_rest());
513 return *this;
514 }
515
522 template <typename... U, enable_if_t<conjunction<negation<is_same<tuple, tuple<U...>>>,
523 inner::tuple_assignable<tuple, const U&...>>::value,
524 int> = 0>
525 NEFORCE_CONSTEXPR14 tuple&
526 operator=(const tuple<U...>& tup) noexcept(inner::tuple_nothrow_assignable<tuple, const U&...>::value) {
527 data_ = tup.data_;
528 get_rest() = tup.get_rest();
529 return *this;
530 }
531
538 template <
539 typename... U,
540 enable_if_t<conjunction<negation<is_same<tuple, tuple<U...>>>, inner::tuple_assignable<tuple, U...>>::value,
541 int> = 0>
542 NEFORCE_CONSTEXPR14 tuple&
543 operator=(tuple<U...>&& tup) noexcept(inner::tuple_nothrow_assignable<tuple, U...>::value) {
544 data_ = _NEFORCE forward<typename tuple<U...>::this_type>(tup.data_);
545 get_rest() = _NEFORCE forward<typename tuple<U...>::super>(tup.get_rest());
546 return *this;
547 }
548
556 template <typename T1, typename T2,
558 NEFORCE_CONSTEXPR14 tuple&
559 operator=(const pair<T1, T2>& pir) noexcept(inner::tuple_nothrow_assignable<tuple, const T1&, const T2&>::value) {
560 data_ = pir.first;
561 get_rest().data_ = pir.second;
562 return *this;
563 }
564
572 template <typename T1, typename T2, enable_if_t<inner::tuple_assignable<tuple, T1, T2>::value, int> = 0>
573 NEFORCE_CONSTEXPR14 tuple&
574 operator=(pair<T1, T2>&& pir) noexcept(inner::tuple_nothrow_assignable<tuple, T1, T2>::value) {
575 data_ = _NEFORCE forward<T1>(pir.first);
576 get_rest().data_ = _NEFORCE forward<T2>(pir.second);
577 return *this;
578 }
579
580 tuple& operator=(const volatile tuple&) = delete;
581
586 NEFORCE_CONSTEXPR14 base_type& get_rest() noexcept { return *this; }
587
592 NEFORCE_CONSTEXPR14 const base_type& get_rest() const noexcept { return *this; }
593
600 template <typename... U>
601 NEFORCE_NODISCARD constexpr bool equal_to(const tuple<U...>& t) const {
602 return data_ == t.data_ && base_type::equal_to(t.get_rest());
603 }
604
611 template <typename... U>
612 NEFORCE_NODISCARD constexpr bool less_than(const tuple<U...>& rhs) const {
613 return data_ < rhs.data_ || (!(rhs.data_ < data_) && base_type::less_than(rhs.get_rest()));
614 }
615
616 using icommon<tuple<This, Rest...>>::operator==;
617 using icommon<tuple<This, Rest...>>::operator!=;
618 using icommon<tuple<This, Rest...>>::operator<;
619 using icommon<tuple<This, Rest...>>::operator>;
620 using icommon<tuple<This, Rest...>>::operator<=;
621 using icommon<tuple<This, Rest...>>::operator>=;
622
623 template <size_t Index, typename... Types>
624 friend constexpr tuple_element_t<Index, Types...>& get(tuple<Types...>&) noexcept;
625 template <size_t Index, typename... Types>
626 friend constexpr const tuple_element_t<Index, Types...>& get(const tuple<Types...>&) noexcept;
627 template <size_t Index, typename... Types>
628 friend constexpr tuple_element_t<Index, Types...>&& get(tuple<Types...>&&) noexcept;
629 template <size_t Index, typename... Types>
630 friend constexpr const tuple_element_t<Index, Types...>&& get(const tuple<Types...>&&) noexcept;
631
632 template <size_t Index, typename... Types>
633 friend constexpr tuple_element_t<Index, Types...>&& pair_get_from_tuple(tuple<Types...>&&) noexcept;
634
639 NEFORCE_NODISCARD constexpr size_t to_hash() const noexcept {
640 return tuple::__broaden_tuple(*this, _NEFORCE index_sequence_for<This, Rest...>());
641 }
642
647 NEFORCE_CONSTEXPR14 void
649 _NEFORCE swap(data_, t.data_);
650 base_type::swap(t.get_rest());
651 }
652};
653#ifdef NEFORCE_STANDARD_17
654template <typename... Types>
655tuple(Types...) -> tuple<Types...>;
656
657template <typename T1, typename T2>
658tuple(pair<T1, T2>) -> tuple<T1, T2>;
659#endif
660
661
669template <size_t Index, typename... Types>
670NEFORCE_NODISCARD constexpr tuple_element_t<Index, Types...>& get(tuple<Types...>& t) noexcept {
671 using T = tuple_element_t<Index, tuple<Types...>>;
672 using tuple_type = tuple_extract_base_t<Index, tuple<Types...>>;
673 return static_cast<T&>(static_cast<tuple_type&>(t).data_);
674}
675
683template <size_t Index, typename... Types>
684NEFORCE_NODISCARD constexpr const tuple_element_t<Index, Types...>& get(const tuple<Types...>& t) noexcept {
685 using T = tuple_element_t<Index, tuple<Types...>>;
686 using tuple_type = tuple_extract_base_t<Index, tuple<Types...>>;
687 return static_cast<const T&>(static_cast<const tuple_type&>(t).data_);
688}
689
697template <size_t Index, typename... Types>
698NEFORCE_NODISCARD constexpr tuple_element_t<Index, Types...>&& get(tuple<Types...>&& t) noexcept {
699 using T = tuple_element_t<Index, tuple<Types...>>;
700 using tuple_type = tuple_extract_base_t<Index, tuple<Types...>>;
701 return static_cast<T&&>(static_cast<tuple_type&&>(t).data_);
702}
703
711template <size_t Index, typename... Types>
712NEFORCE_NODISCARD constexpr const tuple_element_t<Index, Types...>&& get(const tuple<Types...>&& t) noexcept {
713 using T = tuple_element_t<Index, tuple<Types...>>;
714 using tuple_type = tuple_extract_base_t<Index, tuple<Types...>>;
715 return static_cast<const T&&>(static_cast<const tuple_type&&>(t).data_);
716}
717
719NEFORCE_BEGIN_INNER__
727template <size_t Index, typename... Types>
728NEFORCE_NODISCARD constexpr tuple_element_t<Index, Types...>&& __pair_get_from_tuple(tuple<Types...>&& t) noexcept {
729 using T = tuple_element_t<Index, tuple<Types...>>;
730 using tuple_type = tuple_extract_base_t<Index, tuple<Types...>>;
731 return static_cast<T&&>(static_cast<tuple_type&>(t).data_);
732}
733NEFORCE_END_INNER__
734
735template <typename This, typename... Rest>
736template <typename Tag, typename Tuple, size_t... Index,
738constexpr tuple<This, Rest...>::tuple(Tag /*unused*/, Tuple&& tup, index_sequence<Index...> idx) :
739tuple(exact_arg_construct_tag{}, _NEFORCE get<Index>(_NEFORCE forward<Tuple>(tup))...) {}
740
742
749template <typename... Types>
750NEFORCE_NODISCARD constexpr tuple<unwrap_ref_decay_t<Types>...> make_tuple(Types&&... args) {
751 using tuple_type = tuple<unwrap_ref_decay_t<Types>...>;
752 return tuple_type(_NEFORCE forward<Types>(args)...);
753}
754
761template <typename... Types>
762NEFORCE_NODISCARD constexpr tuple<Types&...> tie(Types&... args) noexcept {
763 using tuple_type = tuple<Types&...>;
764 return tuple_type(args...);
765}
766
773template <typename... Types>
774NEFORCE_NODISCARD constexpr tuple<Types&&...> forward_as_tuple(Types&&... args) noexcept {
775 using tuple_type = tuple<Types&&...>;
776 return tuple_type(_NEFORCE forward<Types>(args)...);
777}
778
780NEFORCE_BEGIN_INNER__
781
782template <typename, typename Tuple, typename = make_index_sequence<tuple_size<remove_reference_t<Tuple>>::value>>
783struct constructible_from_tuple : false_type {};
784
785template <typename T, typename Tuple, size_t... Index>
786struct constructible_from_tuple<T, Tuple, index_sequence<Index...>>
787: bool_constant<is_constructible<T, decltype(_NEFORCE get<Index>(_NEFORCE declval<Tuple>()))...>::value> {};
788
798template <typename T, typename Tuple, size_t... Index>
799NEFORCE_NODISCARD constexpr T __broaden_make_from_tuple(Tuple&& tup, index_sequence<Index...> idx) noexcept(
801 return T(_NEFORCE get<Index>(_NEFORCE forward<Tuple>(tup))...);
802}
803
804NEFORCE_END_INNER__
806
807
815template <typename T, typename Tuple, enable_if_t<inner::constructible_from_tuple<T, Tuple>::value, int> = 0>
816NEFORCE_NODISCARD constexpr T make_from_tuple(Tuple&& tup) noexcept(noexcept(inner::__broaden_make_from_tuple<T>(
818 return inner::__broaden_make_from_tuple<T>(_NEFORCE forward<Tuple>(tup),
820}
821
822
824NEFORCE_BEGIN_INNER__
825
826template <typename, typename, typename, size_t, typename...>
827struct __tuple_cat_aux;
828
829template <typename Tuple, size_t... ElementIdx, size_t... TupleIdx, size_t NextTuple>
830struct __tuple_cat_aux<Tuple, index_sequence<ElementIdx...>, index_sequence<TupleIdx...>, NextTuple> {
831 using Ret = tuple<tuple_element_t<ElementIdx, remove_cvref_t<tuple_element_t<TupleIdx, Tuple>>>...>;
832 using ElementIdxSeq = index_sequence<ElementIdx...>;
833 using TupleIdxSeq = index_sequence<TupleIdx...>;
834};
835
836template <typename Tuple, size_t... ElementIdx, size_t... TupleIdx, size_t NextTuple, size_t... NextElement,
837 typename... Rest>
838struct __tuple_cat_aux<Tuple, index_sequence<ElementIdx...>, index_sequence<TupleIdx...>, NextTuple,
839 index_sequence<NextElement...>, Rest...>
840: __tuple_cat_aux<Tuple, index_sequence<ElementIdx..., NextElement...>,
841 index_sequence<TupleIdx..., (NextTuple + 0 * NextElement)...>, NextTuple + 1, Rest...> {};
842
843template <typename... Tuples>
844using tuple_cat_bind_t = __tuple_cat_aux<tuple<Tuples&&...>, index_sequence<>, index_sequence<>, 0,
846
858template <typename Ret, size_t... ElementIdx, size_t... TupleIdx, typename Tuple>
859constexpr Ret __tuple_cat_in_turn(index_sequence<ElementIdx...> ei, index_sequence<TupleIdx...> ti, Tuple tup) {
860 return Ret{_NEFORCE get<ElementIdx>(_NEFORCE get<TupleIdx>(_NEFORCE move(tup)))...};
861}
862
863NEFORCE_END_INNER__
865
866
873template <typename... Tuples>
874NEFORCE_NODISCARD constexpr typename inner::tuple_cat_bind_t<Tuples...>::Ret tuple_cat(Tuples&&... tuples) {
875 using CatImpl = inner::tuple_cat_bind_t<Tuples...>;
876 using Ret = typename CatImpl::Ret;
877 using ElementIdxSeq = typename CatImpl::ElementIdxSeq;
878 using TupleIdxSeq = typename CatImpl::TupleIdxSeq;
879 return inner::__tuple_cat_in_turn<Ret>(ElementIdxSeq{}, TupleIdxSeq{},
880 _NEFORCE forward_as_tuple(_NEFORCE forward<Tuples>(tuples)...));
881}
882 // Tuple
884
885#if !defined(NEFORCE_STANDARD_17)
887NEFORCE_BEGIN_INNER__
888
889template <typename Tuple, size_t Index>
890struct __broadern_tuple_hash_aux {
891 static constexpr size_t hash(const Tuple& tup) {
892 using ElementType = remove_cvref_t<tuple_element_t<Index - 1, Tuple>>;
893 return __broadern_tuple_hash_aux<Tuple, Index - 1>::hash(tup) ^
894 _NEFORCE hash<ElementType>()(_NEFORCE get<Index - 1>(tup));
895 }
896};
897template <typename Tuple>
898struct __broadern_tuple_hash_aux<Tuple, 1> {
899 static constexpr size_t hash(const Tuple& tup) {
900 using ElementType = remove_cvref_t<tuple_element_t<0, Tuple>>;
901 return _NEFORCE hash<ElementType>()(_NEFORCE get<0>(tup));
902 }
903};
904template <typename Tuple>
905struct __broadern_tuple_hash_aux<Tuple, 0> {
906 static constexpr size_t hash(const Tuple& /*unused*/) { return 0; }
907};
908
909NEFORCE_END_INNER__
911#endif // !NEFORCE_STANDARD_17
912
913
914template <typename This, typename... Rest>
915template <typename Tuple, size_t... Idx>
916constexpr size_t tuple<This, Rest...>::__broaden_tuple(const Tuple& tup, index_sequence<Idx...> /*unused*/) noexcept {
917#ifdef NEFORCE_STANDARD_17
918 return (hash<remove_cvref_t<tuple_element_t<Idx, Tuple>>>()(_NEFORCE get<Idx>(tup)) ^ ...);
919#else
920 return inner::__broadern_tuple_hash_aux<Tuple, sizeof...(Idx)>::hash(tup);
921#endif // NEFORCE_STANDARD_17
922}
923
924NEFORCE_END_NAMESPACE__
925
926#ifdef NEFORCE_STANDARD_17
927namespace std {
928 template <typename... Types>
929 struct tuple_size<_NEFORCE tuple<Types...>> : _NEFORCE integral_constant<_NEFORCE size_t, sizeof...(Types)> {};
930
931 template <_NEFORCE size_t I, typename... Types>
932 struct tuple_element<I, _NEFORCE tuple<Types...>> {
933 using type = _NEFORCE tuple_element_t<I, _NEFORCE tuple<Types...>>;
934 };
935} // namespace std
936#endif
937
938#endif // NEFORCE_CORE_UTILITY_TUPLE_HPP__
constexpr T && forward(remove_reference_t< T > &x) noexcept
完美转发左值
enable_if_t< is_void_v< T >, future_result_t< T > > get(future< T > &f)
通用future结果获取函数
integer_sequence< size_t, Values... > index_sequence
索引序列
make_index_sequence< sizeof...(Types)> index_sequence_for
根据类型参数包生成索引序列
make_integer_sequence< size_t, Size > make_index_sequence
生成指定长度的索引序列
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) noexcept(noexcept(inner::__move_aux(first, last, result)))
移动范围元素
void swap()=delete
删除无参数的swap重载
constexpr tuple< unwrap_ref_decay_t< Types >... > make_tuple(Types &&... args)
从参数创建元组
typename tuple_element< Index, Types... >::tuple_type tuple_extract_base_t
获取tuple元素基类型的类型别名
constexpr tuple< Types &... > tie(Types &... args) noexcept
创建引用元组
typename tuple_element< Index, Types... >::type tuple_element_t
tuple_element的类型别名
constexpr T make_from_tuple(Tuple &&tup) noexcept(noexcept(inner::__broaden_make_from_tuple< T >(_NEFORCE forward< Tuple >(tup), make_index_sequence< tuple_size< remove_reference_t< Tuple > >::value >{})))
从元组构造对象
constexpr tuple< Types &&... > forward_as_tuple(Types &&... args) noexcept
创建转发引用元组
constexpr inner::tuple_cat_bind_t< Tuples... >::Ret tuple_cat(Tuples &&... tuples)
连接多个元组
constexpr bool conjunction_v
conjunction的便捷变量模板
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的便捷别名
键值对
类型集合的逻辑与操作
精确参数构造标签
哈希函数的主模板
通用接口,同时具备可比较和可哈希功能
判断类型是否可复制赋值
判断类型是否可默认构造
判断类型是否可隐式默认构造
判断类型是否可移动赋值
判断类型是否可以使用指定参数无异常构造
判断类型是否可无异常复制赋值
判断类型是否可无异常复制构造
判断类型是否可无异常默认构造
判断类型是否可无异常移动赋值
判断类型是否可以与自身无异常交换
判断两个类型是否相同
逻辑非包装器
存储两个值的元组对
tuple & operator=(const volatile tuple &)=delete
禁止volatile拷贝赋值
constexpr const base_type & get_rest() const noexcept
获取剩余元素的元组常量引用
constexpr tuple(Tag, Tuple &&tup)
解包工具构造函数
constexpr tuple & operator=(const pair< T1, T2 > &pir) noexcept(inner::tuple_nothrow_assignable< tuple, const T1 &, const T2 & >::value)
从pair拷贝赋值
tuple(const tuple &)=default
拷贝构造函数
constexpr tuple & operator=(pair< T1, T2 > &&pir) noexcept(inner::tuple_nothrow_assignable< tuple, T1, T2 >::value)
从pair移动赋值
tuple(tuple &&)=default
移动构造函数
constexpr tuple & operator=(tuple< U... > &&tup) noexcept(inner::tuple_nothrow_assignable< tuple, U... >::value)
从其他元组移动赋值
tuple< Rest... > base_type
基类类型,即剩余元素的元组
constexpr size_t to_hash() const noexcept
计算元组的哈希值
This this_type
当前元素类型
constexpr base_type & get_rest() noexcept
获取剩余元素的元组引用
constexpr bool less_than(const tuple< U... > &rhs) const
比较两个元组的大小关系
constexpr tuple(Tag, U1 &&this_arg, U2 &&... rest_arg)
精确参数构造函数
constexpr tuple & operator=(type_identity_t< const tuple & > tup) noexcept(conjunction< is_nothrow_copy_assignable< T >, is_nothrow_copy_assignable< Rest >... >::value)
拷贝赋值运算符
constexpr tuple & operator=(type_identity_t< tuple && > tup) noexcept(conjunction< is_nothrow_move_assignable< T >, is_nothrow_move_assignable< Rest >... >::value)
移动赋值运算符
constexpr tuple & operator=(const tuple< U... > &tup) noexcept(inner::tuple_nothrow_assignable< tuple, const U &... >::value)
从其他元组拷贝赋值
constexpr tuple(Tag, Tuple &&tup, index_sequence< Index... > idx)
解包工具构造函数
constexpr bool equal_to(const tuple< U... > &t) const
比较两个元组是否相等
constexpr void swap(tuple &t) noexcept(conjunction< is_nothrow_swappable< This >, is_nothrow_swappable< Rest >... >::value)
交换两个元组的内容
constexpr void swap(tuple &) noexcept
交换操作
constexpr bool less_than(const tuple &) const noexcept
比较两个空元组的大小关系
constexpr tuple & operator=(const tuple &) noexcept=default
拷贝赋值运算符
constexpr bool equal_to(const tuple &) const noexcept
比较两个空元组是否相等
constexpr tuple() noexcept=default
默认构造函数
constexpr size_t to_hash() const noexcept
计算空元组的哈希值
获取tuple大小的特化
解包工具构造标签