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<> : 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) noexcept {}
178
179 NEFORCE_CONSTEXPR14 tuple& operator=(const tuple&) noexcept = default;
180
185 NEFORCE_NODISCARD NEFORCE_ALWAYS_INLINE constexpr bool equal_to(const tuple&) const noexcept { return true; }
186
191 NEFORCE_NODISCARD NEFORCE_ALWAYS_INLINE constexpr bool less_to(const tuple&) const noexcept { return false; }
192
196 NEFORCE_ALWAYS_INLINE NEFORCE_CONSTEXPR14 void swap(tuple&) noexcept {}
197
202 NEFORCE_NODISCARD NEFORCE_ALWAYS_INLINE constexpr bool operator==(const tuple& rhs) const noexcept {
203 return this->equal_to(rhs);
204 }
205
210 NEFORCE_NODISCARD NEFORCE_ALWAYS_INLINE constexpr bool operator<(const tuple& rhs) const noexcept {
211 return this->less_to(rhs);
212 }
213
218 NEFORCE_NODISCARD NEFORCE_ALWAYS_INLINE constexpr size_t to_hash() const noexcept {
219 return constants::FNV_OFFSET_BASIS;
220 }
221};
222
223
231template <typename This, typename... Rest>
232struct tuple<This, Rest...> : private tuple<Rest...>, icommon<tuple<This, Rest...>> {
233 using this_type = This;
234 using base_type = tuple<Rest...>;
235
236private:
237 this_type data_;
238
247 template <typename Tuple, size_t... Idx>
248 static constexpr size_t __broaden_tuple(const Tuple& tup, _NEFORCE index_sequence<Idx...> idx) noexcept;
249
250public:
259 template <typename Tag, typename U1, typename... U2,
261 constexpr tuple(Tag, U1&& this_arg, U2&&... rest_arg) :
262 base_type(exact_arg_construct_tag{}, _NEFORCE forward<U2>(rest_arg)...),
263 data_(_NEFORCE forward<U1>(this_arg)) {}
264
273 template <typename Tag, typename Tuple, size_t... Index,
275 constexpr tuple(Tag, Tuple&& tup, index_sequence<Index...> idx);
276
283 template <typename Tag, typename Tuple, enable_if_t<is_same<Tag, unpack_utility_construct_tag>::value, int> = 0>
284 constexpr tuple(Tag, Tuple&& tup) :
285 tuple(unpack_utility_construct_tag{}, _NEFORCE forward<Tuple>(tup),
286 make_index_sequence<tuple_size<remove_cvref_t<Tuple>>::value>{}) {}
287
288
289#ifdef NEFORCE_STANDARD_20
294 template <typename T = This,
295 enable_if_t<conjunction_v<is_default_constructible<T>, is_default_constructible<Rest>...>, int> = 0>
302
309 template <typename T = This,
310 enable_if_t<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(
314 tuple(exact_arg_construct_tag{}, this_arg, rest_arg...) {}
315
323 template <typename U1, typename... U2,
324 enable_if_t<conjunction_v<inner::tuple_perfect_forward<tuple, U1, U2...>,
325 inner::tuple_constructible<tuple, U1, U2...>>,
326 int> = 0>
327 constexpr explicit(inner::tuple_explicitly_convertible<tuple, U1, U2...>::value)
328 tuple(U1&& this_arg,
329 U2&&... rest_arg) noexcept(inner::tuple_nothrow_constructible<tuple, U1, U2...>::value) :
330 tuple(exact_arg_construct_tag{}, _NEFORCE forward<U1>(this_arg), _NEFORCE forward<U2>(rest_arg)...) {}
331
337 template <typename... U, enable_if_t<conjunction_v<inner::tuple_constructible<tuple, const U&...>,
338 inner::tuple_convertible<tuple, const tuple<U...>&, U...>>,
339 int> = 0>
340 constexpr explicit(inner::tuple_explicitly_convertible<tuple, const U&...>::value)
341 tuple(const tuple<U...>& tup) noexcept(inner::tuple_nothrow_constructible<tuple, const U&...>::value) :
343
349 template <typename... U, enable_if_t<conjunction_v<inner::tuple_constructible<tuple, U...>,
350 inner::tuple_convertible<tuple, tuple<U...>, U...>>,
351 int> = 0>
352 constexpr explicit(inner::tuple_explicitly_convertible<tuple, U...>::value)
353 tuple(tuple<U...>&& tup) noexcept(inner::tuple_nothrow_constructible<tuple, U...>::value) :
354 tuple(unpack_utility_construct_tag{}, _NEFORCE move(tup)) {}
355
362 template <typename T1, typename T2,
364 constexpr explicit(inner::tuple_explicitly_convertible<tuple, const T1&, const T2&>::value) tuple(
365 const pair<T1, T2>& pir) noexcept(inner::tuple_nothrow_constructible<tuple, const T1&, const T2&>::value) :
367
374 template <typename T1, typename T2, enable_if_t<inner::tuple_constructible<tuple, T1, T2>::value, int> = 0>
375 constexpr explicit(inner::tuple_explicitly_convertible<tuple, T1, T2>::value)
376 tuple(pair<T1, T2>&& pir) noexcept(inner::tuple_nothrow_constructible<tuple, T1, T2>::value) :
377 tuple(unpack_utility_construct_tag{}, _NEFORCE move(pir)) {}
378#else
379 template <typename T = This,
383 int> = 0>
384 explicit tuple() noexcept(
386 base_type(),
387 data_() {}
388
389 template <typename T = This,
390 enable_if_t<conjunction<is_default_constructible<T>, is_default_constructible<Rest>...>::value &&
391 conjunction<is_implicitly_default_constructible<T>,
392 is_implicitly_default_constructible<Rest>...>::value,
393 int> = 0>
394 tuple() noexcept(
395 conjunction<is_nothrow_default_constructible<T>, is_nothrow_default_constructible<Rest>...>::value) :
396 base_type(),
397 data_() {}
398
399 template <typename T = This,
400 enable_if_t<inner::tuple_constructible<tuple, const T&, const Rest&...>::value &&
401 inner::tuple_explicitly_convertible<tuple, const T&, const Rest&...>::value,
402 int> = 0>
403 explicit tuple(const T& this_arg, const Rest&... rest_arg) noexcept(
404 conjunction<is_nothrow_copy_constructible<T>, is_nothrow_copy_constructible<Rest>...>::value) :
405 tuple(exact_arg_construct_tag{}, this_arg, rest_arg...) {}
406
407 template <typename T = This,
408 enable_if_t<inner::tuple_constructible<tuple, const T&, const Rest&...>::value &&
409 !inner::tuple_explicitly_convertible<tuple, const T&, const Rest&...>::value,
410 int> = 0>
411 tuple(const T& this_arg, const Rest&... rest_arg) noexcept(
412 conjunction<is_nothrow_copy_constructible<T>, is_nothrow_copy_constructible<Rest>...>::value) :
413 tuple(exact_arg_construct_tag{}, this_arg, 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 explicit tuple(U1&& this_arg,
421 U2&&... rest_arg) noexcept(inner::tuple_nothrow_constructible<tuple, U1, U2...>::value) :
422 tuple(exact_arg_construct_tag{}, _NEFORCE forward<U1>(this_arg), _NEFORCE forward<U2>(rest_arg)...) {}
423
424 template <typename U1, typename... U2,
425 enable_if_t<conjunction<inner::tuple_constructible<tuple, U1, U2...>,
426 inner::tuple_convertible<tuple, U1, U2...>>::value &&
427 !inner::tuple_explicitly_convertible<tuple, U1, U2...>::value,
428 int> = 0>
429 tuple(U1&& this_arg, U2&&... rest_arg) noexcept(inner::tuple_nothrow_constructible<tuple, U1, U2...>::value) :
430 tuple(exact_arg_construct_tag{}, _NEFORCE forward<U1>(this_arg), _NEFORCE forward<U2>(rest_arg)...) {}
431
432 template <typename... U,
433 enable_if_t<conjunction<inner::tuple_constructible<tuple, const U&...>,
434 inner::tuple_convertible<tuple, const tuple<U...>&, U...>>::value &&
435 inner::tuple_explicitly_convertible<tuple, const U&...>::value,
436 int> = 0>
437 explicit tuple(const tuple<U...>& tup) noexcept(inner::tuple_nothrow_constructible<tuple, const U&...>::value) :
438 tuple(unpack_utility_construct_tag{}, tup) {}
439
440 template <typename... U,
441 enable_if_t<conjunction<inner::tuple_constructible<tuple, const U&...>,
442 inner::tuple_convertible<tuple, const tuple<U...>&, U...>>::value &&
443 !inner::tuple_explicitly_convertible<tuple, const U&...>::value,
444 int> = 0>
445 tuple(const tuple<U...>& tup) noexcept(inner::tuple_nothrow_constructible<tuple, const U&...>::value) :
446 tuple(unpack_utility_construct_tag{}, tup) {}
447
448 template <typename... U, enable_if_t<conjunction<inner::tuple_constructible<tuple, U...>,
449 inner::tuple_convertible<tuple, tuple<U...>, U...>>::value &&
450 inner::tuple_explicitly_convertible<tuple, U...>::value,
451 int> = 0>
452 explicit tuple(tuple<U...>&& tup) noexcept(inner::tuple_nothrow_constructible<tuple, U...>::value) :
453 tuple(unpack_utility_construct_tag{}, _NEFORCE move(tup)) {}
454
455 template <typename... U, enable_if_t<conjunction<inner::tuple_constructible<tuple, U...>,
456 inner::tuple_convertible<tuple, tuple<U...>, U...>>::value &&
457 !inner::tuple_explicitly_convertible<tuple, U...>::value,
458 int> = 0>
459 tuple(tuple<U...>&& tup) noexcept(inner::tuple_nothrow_constructible<tuple, U...>::value) :
460 tuple(unpack_utility_construct_tag{}, _NEFORCE move(tup)) {}
461
462 template <typename T1, typename T2,
463 enable_if_t<inner::tuple_constructible<tuple, const T1&, const T2&>::value &&
464 inner::tuple_explicitly_convertible<tuple, const T1&, const T2&>::value,
465 int> = 0>
466 explicit tuple(const pair<T1, T2>& pir) noexcept(
467 inner::tuple_nothrow_constructible<tuple, const T1&, const T2&>::value) :
468 tuple(unpack_utility_construct_tag{}, pir) {}
469
470 template <typename T1, typename T2,
471 enable_if_t<inner::tuple_constructible<tuple, const T1&, const T2&>::value &&
472 !inner::tuple_explicitly_convertible<tuple, const T1&, const T2&>::value,
473 int> = 0>
474 tuple(const pair<T1, T2>& pir) noexcept(inner::tuple_nothrow_constructible<tuple, const T1&, const T2&>::value) :
475 tuple(unpack_utility_construct_tag{}, pir) {}
476
477 template <typename T1, typename T2,
478 enable_if_t<inner::tuple_constructible<tuple, T1, T2>::value &&
479 inner::tuple_explicitly_convertible<tuple, T1, T2>::value,
480 int> = 0>
481 explicit tuple(pair<T1, T2>&& pir) noexcept(inner::tuple_nothrow_constructible<tuple, T1, T2>::value) :
482 tuple(unpack_utility_construct_tag{}, _NEFORCE move(pir)) {}
483
484 template <typename T1, typename T2,
485 enable_if_t<inner::tuple_constructible<tuple, T1, T2>::value &&
486 !inner::tuple_explicitly_convertible<tuple, T1, T2>::value,
487 int> = 0>
488 tuple(pair<T1, T2>&& pir) noexcept(inner::tuple_nothrow_constructible<tuple, T1, T2>::value) :
489 tuple(unpack_utility_construct_tag{}, _NEFORCE move(pir)) {}
490#endif
491
492 tuple(const tuple&) = default;
493 tuple(tuple&&) = default;
494
501 template <typename T = This,
503 NEFORCE_CONSTEXPR14 tuple& operator=(type_identity_t<const tuple&> tup) noexcept(
505 data_ = tup.data_;
506 get_rest() = tup.get_rest();
507 return *this;
508 }
509
516 template <typename T = This,
518 NEFORCE_CONSTEXPR14 tuple& operator=(type_identity_t<tuple&&> tup) noexcept(
520 data_ = _NEFORCE forward<T>(tup.data_);
521 get_rest() = _NEFORCE forward<base_type>(tup.get_rest());
522 return *this;
523 }
524
531 template <typename... U, enable_if_t<conjunction<negation<is_same<tuple, tuple<U...>>>,
532 inner::tuple_assignable<tuple, const U&...>>::value,
533 int> = 0>
534 NEFORCE_CONSTEXPR14 tuple&
535 operator=(const tuple<U...>& tup) noexcept(inner::tuple_nothrow_assignable<tuple, const U&...>::value) {
536 data_ = tup.data_;
537 get_rest() = tup.get_rest();
538 return *this;
539 }
540
547 template <
548 typename... U,
549 enable_if_t<conjunction<negation<is_same<tuple, tuple<U...>>>, inner::tuple_assignable<tuple, U...>>::value,
550 int> = 0>
551 NEFORCE_CONSTEXPR14 tuple&
552 operator=(tuple<U...>&& tup) noexcept(inner::tuple_nothrow_assignable<tuple, U...>::value) {
553 data_ = _NEFORCE forward<typename tuple<U...>::this_type>(tup.data_);
554 get_rest() = _NEFORCE forward<typename tuple<U...>::super>(tup.get_rest());
555 return *this;
556 }
557
565 template <typename T1, typename T2,
567 NEFORCE_CONSTEXPR14 tuple&
568 operator=(const pair<T1, T2>& pir) noexcept(inner::tuple_nothrow_assignable<tuple, const T1&, const T2&>::value) {
569 data_ = pir.first;
570 get_rest().data_ = pir.second;
571 return *this;
572 }
573
581 template <typename T1, typename T2, enable_if_t<inner::tuple_assignable<tuple, T1, T2>::value, int> = 0>
582 NEFORCE_CONSTEXPR14 tuple&
583 operator=(pair<T1, T2>&& pir) noexcept(inner::tuple_nothrow_assignable<tuple, T1, T2>::value) {
584 data_ = _NEFORCE forward<T1>(pir.first);
585 get_rest().data_ = _NEFORCE forward<T2>(pir.second);
586 return *this;
587 }
588
589 tuple& operator=(const volatile tuple&) = delete;
590
595 NEFORCE_CONSTEXPR14 base_type& get_rest() noexcept { return *this; }
596
601 NEFORCE_CONSTEXPR14 const base_type& get_rest() const noexcept { return *this; }
602
609 template <typename... U>
610 NEFORCE_NODISCARD constexpr bool equal_to(const tuple<U...>& t) const {
611 return data_ == t.data_ && base_type::equal_to(t.get_rest());
612 }
613
620 template <typename... U>
621 NEFORCE_NODISCARD constexpr bool less_to(const tuple<U...>& rhs) const {
622 return data_ < rhs.data_ || (!(rhs.data_ < data_) && base_type::less_to(rhs.get_rest()));
623 }
624
625 template <size_t Index, typename... Types>
626 friend constexpr tuple_element_t<Index, Types...>& get(tuple<Types...>&) noexcept;
627 template <size_t Index, typename... Types>
628 friend constexpr const tuple_element_t<Index, Types...>& get(const tuple<Types...>&) noexcept;
629 template <size_t Index, typename... Types>
630 friend constexpr tuple_element_t<Index, Types...>&& get(tuple<Types...>&&) noexcept;
631 template <size_t Index, typename... Types>
632 friend constexpr const tuple_element_t<Index, Types...>&& get(const tuple<Types...>&&) noexcept;
633
634 template <size_t Index, typename... Types>
635 friend constexpr tuple_element_t<Index, Types...>&& pair_get_from_tuple(tuple<Types...>&&) noexcept;
636
638 NEFORCE_NODISCARD constexpr bool operator==(const tuple& rhs) const noexcept { return this->equal_to(rhs); }
640 NEFORCE_NODISCARD constexpr bool operator<(const tuple& rhs) const noexcept { return this->less_to(rhs); }
641
646 NEFORCE_NODISCARD constexpr size_t to_hash() const noexcept {
647 return tuple::__broaden_tuple(*this, _NEFORCE index_sequence_for<This, Rest...>());
648 }
649
654 NEFORCE_CONSTEXPR14 void
656 _NEFORCE swap(data_, t.data_);
657 base_type::swap(t.get_rest());
658 }
659};
660#ifdef NEFORCE_STANDARD_17
661template <typename... Types>
662tuple(Types...) -> tuple<Types...>;
663
664template <typename T1, typename T2>
665tuple(pair<T1, T2>) -> tuple<T1, T2>;
666#endif
667
668
676template <size_t Index, typename... Types>
677NEFORCE_NODISCARD constexpr tuple_element_t<Index, Types...>& get(tuple<Types...>& t) noexcept {
678 using T = tuple_element_t<Index, tuple<Types...>>;
679 using tuple_type = tuple_extract_base_t<Index, tuple<Types...>>;
680 return static_cast<T&>(static_cast<tuple_type&>(t).data_);
681}
682
690template <size_t Index, typename... Types>
691NEFORCE_NODISCARD constexpr const tuple_element_t<Index, Types...>& get(const tuple<Types...>& t) noexcept {
692 using T = tuple_element_t<Index, tuple<Types...>>;
693 using tuple_type = tuple_extract_base_t<Index, tuple<Types...>>;
694 return static_cast<const T&>(static_cast<const tuple_type&>(t).data_);
695}
696
704template <size_t Index, typename... Types>
705NEFORCE_NODISCARD constexpr tuple_element_t<Index, Types...>&& get(tuple<Types...>&& t) noexcept {
706 using T = tuple_element_t<Index, tuple<Types...>>;
707 using tuple_type = tuple_extract_base_t<Index, tuple<Types...>>;
708 return static_cast<T&&>(static_cast<tuple_type&&>(t).data_);
709}
710
718template <size_t Index, typename... Types>
719NEFORCE_NODISCARD constexpr const tuple_element_t<Index, Types...>&& get(const tuple<Types...>&& t) noexcept {
720 using T = tuple_element_t<Index, tuple<Types...>>;
721 using tuple_type = tuple_extract_base_t<Index, tuple<Types...>>;
722 return static_cast<const T&&>(static_cast<const tuple_type&&>(t).data_);
723}
724
726NEFORCE_BEGIN_INNER__
734template <size_t Index, typename... Types>
735NEFORCE_NODISCARD constexpr tuple_element_t<Index, Types...>&& __pair_get_from_tuple(tuple<Types...>&& t) noexcept {
736 using T = tuple_element_t<Index, tuple<Types...>>;
737 using tuple_type = tuple_extract_base_t<Index, tuple<Types...>>;
738 return static_cast<T&&>(static_cast<tuple_type&>(t).data_);
739}
740NEFORCE_END_INNER__
741
742template <typename This, typename... Rest>
743template <typename Tag, typename Tuple, size_t... Index,
745constexpr tuple<This, Rest...>::tuple(Tag, Tuple&& tup, index_sequence<Index...> idx) :
746tuple(exact_arg_construct_tag{}, _NEFORCE get<Index>(_NEFORCE forward<Tuple>(tup))...) {}
747
749
756template <typename... Types>
757NEFORCE_NODISCARD constexpr tuple<unwrap_ref_decay_t<Types>...> make_tuple(Types&&... args) {
758 using tuple_type = tuple<unwrap_ref_decay_t<Types>...>;
759 return tuple_type(_NEFORCE forward<Types>(args)...);
760}
761
768template <typename... Types>
769NEFORCE_NODISCARD constexpr tuple<Types&...> tie(Types&... args) noexcept {
770 using tuple_type = tuple<Types&...>;
771 return tuple_type(args...);
772}
773
780template <typename... Types>
781NEFORCE_NODISCARD constexpr tuple<Types&&...> forward_as_tuple(Types&&... args) noexcept {
782 using tuple_type = tuple<Types&&...>;
783 return tuple_type(_NEFORCE forward<Types>(args)...);
784}
785
787NEFORCE_BEGIN_INNER__
788
789template <typename, typename Tuple, typename = make_index_sequence<tuple_size<remove_reference_t<Tuple>>::value>>
790struct constructible_from_tuple : false_type {};
791
792template <typename T, typename Tuple, size_t... Index>
793struct constructible_from_tuple<T, Tuple, index_sequence<Index...>>
794: bool_constant<is_constructible<T, decltype(_NEFORCE get<Index>(_NEFORCE declval<Tuple>()))...>::value> {};
795
805template <typename T, typename Tuple, size_t... Index>
806NEFORCE_NODISCARD constexpr T __broaden_make_from_tuple(Tuple&& tup, index_sequence<Index...> idx) noexcept(
808 return T(_NEFORCE get<Index>(_NEFORCE forward<Tuple>(tup))...);
809}
810
811NEFORCE_END_INNER__
813
814
822template <typename T, typename Tuple, enable_if_t<inner::constructible_from_tuple<T, Tuple>::value, int> = 0>
823NEFORCE_NODISCARD constexpr T make_from_tuple(Tuple&& tup) noexcept(noexcept(inner::__broaden_make_from_tuple<T>(
825 return inner::__broaden_make_from_tuple<T>(_NEFORCE forward<Tuple>(tup),
827}
828
829
831NEFORCE_BEGIN_INNER__
832
833template <typename, typename, typename, size_t, typename...>
834struct __tuple_cat_aux;
835
836template <typename Tuple, size_t... ElementIdx, size_t... TupleIdx, size_t NextTuple>
837struct __tuple_cat_aux<Tuple, index_sequence<ElementIdx...>, index_sequence<TupleIdx...>, NextTuple> {
838 using Ret = tuple<tuple_element_t<ElementIdx, remove_cvref_t<tuple_element_t<TupleIdx, Tuple>>>...>;
839 using ElementIdxSeq = index_sequence<ElementIdx...>;
840 using TupleIdxSeq = index_sequence<TupleIdx...>;
841};
842
843template <typename Tuple, size_t... ElementIdx, size_t... TupleIdx, size_t NextTuple, size_t... NextElement,
844 typename... Rest>
845struct __tuple_cat_aux<Tuple, index_sequence<ElementIdx...>, index_sequence<TupleIdx...>, NextTuple,
846 index_sequence<NextElement...>, Rest...>
847: __tuple_cat_aux<Tuple, index_sequence<ElementIdx..., NextElement...>,
848 index_sequence<TupleIdx..., (NextTuple + 0 * NextElement)...>, NextTuple + 1, Rest...> {};
849
850template <typename... Tuples>
851using tuple_cat_bind_t = __tuple_cat_aux<tuple<Tuples&&...>, index_sequence<>, index_sequence<>, 0,
853
865template <typename Ret, size_t... ElementIdx, size_t... TupleIdx, typename Tuple>
866constexpr Ret __tuple_cat_in_turn(index_sequence<ElementIdx...> ei, index_sequence<TupleIdx...> ti, Tuple tup) {
867 return Ret{_NEFORCE get<ElementIdx>(_NEFORCE get<TupleIdx>(_NEFORCE move(tup)))...};
868}
869
870NEFORCE_END_INNER__
872
873
880template <typename... Tuples>
881NEFORCE_NODISCARD constexpr typename inner::tuple_cat_bind_t<Tuples...>::Ret tuple_cat(Tuples&&... tuples) {
882 using CatImpl = inner::tuple_cat_bind_t<Tuples...>;
883 using Ret = typename CatImpl::Ret;
884 using ElementIdxSeq = typename CatImpl::ElementIdxSeq;
885 using TupleIdxSeq = typename CatImpl::TupleIdxSeq;
886 return inner::__tuple_cat_in_turn<Ret>(ElementIdxSeq{}, TupleIdxSeq{},
887 _NEFORCE forward_as_tuple(_NEFORCE forward<Tuples>(tuples)...));
888}
889 // Tuple
891
892#if !defined(NEFORCE_STANDARD_17)
894NEFORCE_BEGIN_INNER__
895
896template <typename Tuple, size_t Index>
897struct __broadern_tuple_hash_aux {
898 static constexpr size_t hash(const Tuple& tup) {
899 using ElementType = remove_cvref_t<tuple_element_t<Index - 1, Tuple>>;
900 return __broadern_tuple_hash_aux<Tuple, Index - 1>::hash(tup) ^
901 _NEFORCE hash<ElementType>()(_NEFORCE get<Index - 1>(tup));
902 }
903};
904template <typename Tuple>
905struct __broadern_tuple_hash_aux<Tuple, 1> {
906 static constexpr size_t hash(const Tuple& tup) {
907 using ElementType = remove_cvref_t<tuple_element_t<0, Tuple>>;
908 return _NEFORCE hash<ElementType>()(_NEFORCE get<0>(tup));
909 }
910};
911template <typename Tuple>
912struct __broadern_tuple_hash_aux<Tuple, 0> {
913 static constexpr size_t hash(const Tuple&) { return 0; }
914};
915
916NEFORCE_END_INNER__
918#endif // !NEFORCE_STANDARD_17
919
920
921template <typename This, typename... Rest>
922template <typename Tuple, size_t... Idx>
923constexpr size_t tuple<This, Rest...>::__broaden_tuple(const Tuple& tup, index_sequence<Idx...>) noexcept {
924#ifdef NEFORCE_STANDARD_17
925 return (hash<remove_cvref_t<tuple_element_t<Idx, Tuple>>>()(_NEFORCE get<Idx>(tup)) ^ ...);
926#else
927 return inner::__broadern_tuple_hash_aux<Tuple, sizeof...(Idx)>::hash(tup);
928#endif // NEFORCE_STANDARD_17
929}
930
931NEFORCE_END_NAMESPACE__
932
933#ifdef NEFORCE_STANDARD_17
934namespace std {
935 template <typename... Types>
936 struct tuple_size<_NEFORCE tuple<Types...>> : _NEFORCE integral_constant<_NEFORCE size_t, sizeof...(Types)> {};
937
938 template <_NEFORCE size_t I, typename... Types>
939 struct tuple_element<I, _NEFORCE tuple<Types...>> {
940 using type = _NEFORCE tuple_element_t<I, _NEFORCE tuple<Types...>>;
941 };
942} // namespace std
943#endif
944
945#endif // NEFORCE_CORE_UTILITY_TUPLE_HPP__
NEFORCE_NODISCARD constexpr T && forward(remove_reference_t< T > &x) noexcept
完美转发左值
NEFORCE_ALWAYS_INLINE 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重载
NEFORCE_NODISCARD constexpr tuple< unwrap_ref_decay_t< Types >... > make_tuple(Types &&... args)
从参数创建元组
typename tuple_element< Index, Types... >::tuple_type tuple_extract_base_t
获取tuple元素基类型的类型别名
NEFORCE_NODISCARD 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 >{})))
从元组构造对象
NEFORCE_NODISCARD constexpr inner::tuple_cat_bind_t< Tuples... >::Ret tuple_cat(Tuples &&... tuples)
连接多个元组
NEFORCE_NODISCARD constexpr tuple< Types &&... > forward_as_tuple(Types &&... args) noexcept
创建转发引用元组
NEFORCE_NODISCARD constexpr tuple< Types &... > tie(Types &... args) noexcept
创建引用元组
typename tuple_element< Index, Types... >::type tuple_element_t
tuple_element的类型别名
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
布尔常量包装器
NEFORCE_INLINE17 constexpr bool conjunction_v
conjunction的便捷变量模板
typename enable_if< Test, T >::type enable_if_t
enable_if的便捷别名
键值对
类型集合的逻辑与操作
精确参数构造标签
哈希函数的主模板
通用接口,同时具备可比较和可哈希功能
判断类型是否可复制赋值
判断类型是否可默认构造
判断类型是否可隐式默认构造
判断类型是否可移动赋值
判断类型是否可以使用指定参数无异常构造
判断类型是否可无异常复制赋值
判断类型是否可无异常复制构造
判断类型是否可无异常默认构造
判断类型是否可无异常移动赋值
判断类型是否可以与自身无异常交换
判断两个类型是否相同
逻辑非包装器
存储两个值的元组对
NEFORCE_CONSTEXPR14 tuple & operator=(type_identity_t< tuple && > tup) noexcept(conjunction< is_nothrow_move_assignable< T >, is_nothrow_move_assignable< Rest >... >::value)
移动赋值运算符
tuple & operator=(const volatile tuple &)=delete
禁止volatile拷贝赋值
NEFORCE_CONSTEXPR14 tuple & operator=(type_identity_t< const tuple & > tup) noexcept(conjunction< is_nothrow_copy_assignable< T >, is_nothrow_copy_assignable< Rest >... >::value)
拷贝赋值运算符
NEFORCE_CONSTEXPR14 tuple & operator=(const tuple< U... > &tup) noexcept(inner::tuple_nothrow_assignable< tuple, const U &... >::value)
从其他元组拷贝赋值
constexpr tuple(Tag, Tuple &&tup)
解包工具构造函数
tuple(const tuple &)=default
拷贝构造函数
NEFORCE_NODISCARD constexpr size_t to_hash() const noexcept
计算元组的哈希值
tuple(tuple &&)=default
移动构造函数
tuple< Rest... > base_type
基类类型,即剩余元素的元组
NEFORCE_NODISCARD constexpr bool equal_to(const tuple< U... > &t) const
比较两个元组是否相等
NEFORCE_CONSTEXPR14 tuple & operator=(pair< T1, T2 > &&pir) noexcept(inner::tuple_nothrow_assignable< tuple, T1, T2 >::value)
从pair移动赋值
This this_type
当前元素类型
NEFORCE_NODISCARD constexpr bool operator<(const tuple &rhs) const noexcept
小于比较运算符
NEFORCE_CONSTEXPR14 tuple & operator=(const pair< T1, T2 > &pir) noexcept(inner::tuple_nothrow_assignable< tuple, const T1 &, const T2 & >::value)
从pair拷贝赋值
NEFORCE_NODISCARD constexpr bool less_to(const tuple< U... > &rhs) const
比较两个元组的大小关系
constexpr tuple(Tag, U1 &&this_arg, U2 &&... rest_arg)
精确参数构造函数
NEFORCE_CONSTEXPR14 base_type & get_rest() noexcept
获取剩余元素的元组引用
NEFORCE_CONSTEXPR14 void swap(tuple &t) noexcept(conjunction< is_nothrow_swappable< This >, is_nothrow_swappable< Rest >... >::value)
交换两个元组的内容
constexpr tuple(Tag, Tuple &&tup, index_sequence< Index... > idx)
解包工具构造函数
NEFORCE_CONSTEXPR14 tuple & operator=(tuple< U... > &&tup) noexcept(inner::tuple_nothrow_assignable< tuple, U... >::value)
从其他元组移动赋值
NEFORCE_CONSTEXPR14 const base_type & get_rest() const noexcept
获取剩余元素的元组常量引用
NEFORCE_CONSTEXPR14 tuple & operator=(const tuple &) noexcept=default
拷贝赋值运算符
NEFORCE_NODISCARD NEFORCE_ALWAYS_INLINE constexpr bool operator==(const tuple &rhs) const noexcept
相等比较运算符
NEFORCE_NODISCARD NEFORCE_ALWAYS_INLINE constexpr size_t to_hash() const noexcept
计算空元组的哈希值
NEFORCE_ALWAYS_INLINE NEFORCE_CONSTEXPR14 void swap(tuple &) noexcept
交换操作
NEFORCE_NODISCARD NEFORCE_ALWAYS_INLINE constexpr bool operator<(const tuple &rhs) const noexcept
小于比较运算符
NEFORCE_NODISCARD NEFORCE_ALWAYS_INLINE constexpr bool less_to(const tuple &) const noexcept
比较两个空元组的大小关系
constexpr tuple() noexcept=default
默认构造函数
NEFORCE_NODISCARD NEFORCE_ALWAYS_INLINE constexpr bool equal_to(const tuple &) const noexcept
比较两个空元组是否相等
获取tuple大小的特化
解包工具构造标签