1#ifndef NEFORCE_CORE_UTILITY_TUPLE_HPP__
2#define NEFORCE_CORE_UTILITY_TUPLE_HPP__
12NEFORCE_BEGIN_NAMESPACE__
17template <
bool Same,
typename Dest,
typename... Srcs>
18struct __tuple_constructible_aux :
false_type {};
20template <
typename... Dests,
typename... Srcs>
21struct __tuple_constructible_aux<true, tuple<Dests...>, Srcs...>
22:
bool_constant<conjunction<is_constructible<Dests, Srcs>...>::value> {};
30template <
typename Dest,
typename... Srcs>
31struct tuple_constructible
32:
bool_constant<inner::__tuple_constructible_aux<tuple_size<Dest>::value == sizeof...(Srcs), Dest, Srcs...>::value> {};
35template <
bool Same,
typename Dest,
typename... Srcs>
36struct __tuple_explicitly_convertible_aux :
false_type {};
38template <
typename... Dests,
typename... Srcs>
39struct __tuple_explicitly_convertible_aux<true, tuple<Dests...>, Srcs...>
40:
bool_constant<!conjunction<is_convertible<Srcs, Dests>...>::value> {};
48template <
typename Dest,
typename... Srcs>
49struct tuple_explicitly_convertible
51 inner::__tuple_explicitly_convertible_aux<tuple_size<Dest>::value == sizeof...(Srcs), Dest, Srcs...>::value> {
62template <
typename Tuple1,
typename Tuple2,
typename... U>
63struct tuple_perfect_forward :
true_type {};
65template <
typename Tuple1,
typename Tuple2>
66struct tuple_perfect_forward<Tuple1, Tuple2> :
bool_constant<!is_same<Tuple1, remove_cvref_t<Tuple2>>::value> {};
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> {};
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> {};
79template <
bool Same,
typename Dest,
typename... Srcs>
80struct __tuple_nothrow_constructible_aux :
false_type {};
82template <
typename... Dests,
typename... Srcs>
83struct __tuple_nothrow_constructible_aux<true, tuple<Dests...>, Srcs...>
84:
bool_constant<conjunction<is_nothrow_constructible<Dests, Srcs>...>::value> {};
92template <
typename Dest,
typename... Srcs>
93struct tuple_nothrow_constructible
95 inner::__tuple_nothrow_constructible_aux<tuple_size<Dest>::value == sizeof...(Srcs), Dest, Srcs...>::value> {
99template <
typename Self,
typename Tuple,
typename... U>
100struct __tuple_convertible_aux :
true_type {};
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> {};
113template <
typename Self,
typename Tuple,
typename... U>
114struct tuple_convertible :
bool_constant<inner::__tuple_convertible_aux<Self, Tuple, U...>::value> {};
117template <
bool Same,
typename Dest,
typename... Srcs>
120template <
typename... Dests,
typename... Srcs>
121struct __tuple_assignable_aux<true, tuple<Dests...>, Srcs...>
122:
bool_constant<conjunction<is_assignable<Dests&, Srcs>...>::value> {};
130template <
typename Dest,
typename... Srcs>
131struct tuple_assignable
132:
bool_constant<inner::__tuple_assignable_aux<tuple_size<Dest>::value == sizeof...(Srcs), Dest, Srcs...>::value> {};
135template <
bool Same,
typename Dest,
typename... Srcs>
136struct __tuple_nothrow_assignable_aux :
false_type {};
138template <
typename... Dests,
typename... Srcs>
139struct __tuple_nothrow_assignable_aux<true, tuple<Dests...>, Srcs...>
140:
bool_constant<conjunction<is_nothrow_assignable<Dests&, Srcs>...>::value> {};
148template <
typename Dest,
typename... Srcs>
149struct tuple_nothrow_assignable
151 inner::__tuple_nothrow_assignable_aux<tuple_size<Dest>::value == sizeof...(Srcs), Dest, Srcs...>::value> {};
169 constexpr tuple() noexcept = default;
177 constexpr explicit
tuple(Tag) noexcept {}
185 NEFORCE_NODISCARD NEFORCE_ALWAYS_INLINE
constexpr bool equal_to(
const tuple&)
const noexcept {
return true; }
191 NEFORCE_NODISCARD NEFORCE_ALWAYS_INLINE
constexpr bool less_to(
const tuple&)
const noexcept {
return false; }
196 NEFORCE_ALWAYS_INLINE NEFORCE_CONSTEXPR14
void swap(
tuple&)
noexcept {}
202 NEFORCE_NODISCARD NEFORCE_ALWAYS_INLINE
constexpr bool operator==(
const tuple& rhs)
const noexcept {
210 NEFORCE_NODISCARD NEFORCE_ALWAYS_INLINE
constexpr bool operator<(
const tuple& rhs)
const noexcept {
218 NEFORCE_NODISCARD NEFORCE_ALWAYS_INLINE
constexpr size_t to_hash() const noexcept {
219 return constants::FNV_OFFSET_BASIS;
231template <
typename This,
typename... Rest>
247 template <
typename Tuple,
size_t... Idx>
259 template <
typename Tag,
typename U1,
typename... U2,
261 constexpr tuple(Tag, U1&& this_arg, U2&&... rest_arg) :
263 data_(_NEFORCE
forward<U1>(this_arg)) {}
273 template <
typename Tag,
typename Tuple,
size_t... Index,
283 template <typename Tag, typename Tuple, enable_if_t<is_same<Tag, unpack_utility_construct_tag>::value,
int> = 0>
289#ifdef NEFORCE_STANDARD_20
294 template <
typename T = This,
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(
323 template <
typename U1,
typename... U2,
325 inner::tuple_constructible<tuple, U1, U2...>>,
327 constexpr explicit(inner::tuple_explicitly_convertible<
tuple, U1, U2...>::value)
329 U2&&... rest_arg)
noexcept(inner::tuple_nothrow_constructible<
tuple, U1, U2...>::value) :
338 inner::tuple_convertible<tuple,
const tuple<U...>&, U...>>,
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) :
350 inner::tuple_convertible<tuple, tuple<U...>, U...>>,
352 constexpr explicit(inner::tuple_explicitly_convertible<
tuple, U...>::value)
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) :
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) :
379 template <
typename T = This,
384 explicit tuple() noexcept(
389 template <
typename T = This,
391 conjunction<is_implicitly_default_constructible<T>,
392 is_implicitly_default_constructible<Rest>...>::value,
395 conjunction<is_nothrow_default_constructible<T>, is_nothrow_default_constructible<Rest>...>::value) :
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,
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...) {}
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,
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...) {}
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,
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)...) {}
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,
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)...) {}
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,
437 explicit tuple(
const tuple<U...>& tup)
noexcept(inner::tuple_nothrow_constructible<tuple,
const U&...>::value) :
438 tuple(unpack_utility_construct_tag{}, tup) {}
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,
445 tuple(
const tuple<U...>& tup)
noexcept(inner::tuple_nothrow_constructible<tuple,
const U&...>::value) :
446 tuple(unpack_utility_construct_tag{}, tup) {}
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,
452 explicit tuple(tuple<U...>&& tup)
noexcept(inner::tuple_nothrow_constructible<tuple, U...>::value) :
453 tuple(unpack_utility_construct_tag{}, _NEFORCE
move(tup)) {}
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,
459 tuple(tuple<U...>&& tup)
noexcept(inner::tuple_nothrow_constructible<tuple, U...>::value) :
460 tuple(unpack_utility_construct_tag{}, _NEFORCE
move(tup)) {}
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,
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) {}
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,
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) {}
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,
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)) {}
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,
488 tuple(pair<T1, T2>&& pir)
noexcept(inner::tuple_nothrow_constructible<tuple, T1, T2>::value) :
489 tuple(unpack_utility_construct_tag{}, _NEFORCE
move(pir)) {}
501 template <
typename T = This,
516 template <
typename T = This,
532 inner::tuple_assignable<tuple,
const U&...>>::value,
534 NEFORCE_CONSTEXPR14 tuple&
551 NEFORCE_CONSTEXPR14 tuple&
565 template <
typename T1,
typename T2,
567 NEFORCE_CONSTEXPR14 tuple&
581 template <typename T1, typename T2, enable_if_t<inner::tuple_assignable<tuple, T1, T2>::value,
int> = 0>
582 NEFORCE_CONSTEXPR14 tuple&
609 template <
typename... U>
611 return data_ == t.data_ && base_type::equal_to(t.get_rest());
620 template <
typename... U>
622 return data_ < rhs.data_ || (!(rhs.data_ < data_) && base_type::less_to(rhs.get_rest()));
625 template <
size_t Index,
typename... Types>
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>
631 template <
size_t Index, typename... Types>
632 friend constexpr const
tuple_element_t<Index, Types...>&&
get(const tuple<Types...>&&) noexcept;
634 template <
size_t Index, typename... Types>
635 friend constexpr
tuple_element_t<Index, Types...>&& pair_get_from_tuple(tuple<Types...>&&) noexcept;
638 NEFORCE_NODISCARD constexpr
bool operator==(const
tuple& rhs) const noexcept {
return this->
equal_to(rhs); }
646 NEFORCE_NODISCARD
constexpr size_t to_hash() const noexcept {
654 NEFORCE_CONSTEXPR14
void
656 _NEFORCE
swap(data_, t.data_);
657 base_type::swap(t.get_rest());
660#ifdef NEFORCE_STANDARD_17
661template <
typename... Types>
662tuple(Types...) -> tuple<Types...>;
664template <
typename T1,
typename T2>
676template <
size_t Index,
typename... Types>
680 return static_cast<T&
>(
static_cast<tuple_type&
>(t).data_);
690template <
size_t Index,
typename... Types>
694 return static_cast<const T&
>(
static_cast<const tuple_type&
>(t).data_);
704template <
size_t Index,
typename... Types>
708 return static_cast<T&&
>(
static_cast<tuple_type&&
>(t).data_);
718template <
size_t Index,
typename... Types>
722 return static_cast<const T&&
>(
static_cast<const tuple_type&&
>(t).data_);
734template <
size_t Index,
typename... Types>
735NEFORCE_NODISCARD
constexpr tuple_element_t<Index, Types...>&& __pair_get_from_tuple(tuple<Types...>&& t)
noexcept {
738 return static_cast<T&&
>(
static_cast<tuple_type&
>(t).data_);
742template <
typename This,
typename... Rest>
743template <
typename Tag,
typename Tuple,
size_t... Index,
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>...>;
768template <
typename... Types>
769NEFORCE_NODISCARD
constexpr tuple<Types&...>
tie(Types&... args)
noexcept {
770 using tuple_type = tuple<Types&...>;
771 return tuple_type(args...);
780template <
typename... Types>
782 using tuple_type = tuple<Types&&...>;
789template <
typename,
typename Tuple,
typename = make_index_sequence<tuple_size<remove_reference_t<Tuple>>::value>>
790struct constructible_from_tuple :
false_type {};
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> {};
805template <
typename T,
typename Tuple,
size_t... Index>
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),
833template <
typename,
typename,
typename,
size_t,
typename...>
834struct __tuple_cat_aux;
836template <
typename Tuple,
size_t... ElementIdx,
size_t... TupleIdx,
size_t NextTuple>
838 using Ret = tuple<tuple_element_t<ElementIdx, remove_cvref_t<tuple_element_t<TupleIdx, Tuple>>>...>;
843template <
typename Tuple,
size_t... ElementIdx,
size_t... TupleIdx,
size_t NextTuple,
size_t... NextElement,
847: __tuple_cat_aux<Tuple, index_sequence<ElementIdx..., NextElement...>,
848 index_sequence<TupleIdx..., (NextTuple + 0 * NextElement)...>, NextTuple + 1, Rest...> {};
850template <
typename... Tuples>
865template <
typename Ret,
size_t... ElementIdx,
size_t... TupleIdx,
typename Tuple>
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{},
892#if !defined(NEFORCE_STANDARD_17)
896template <
typename Tuple,
size_t Index>
897struct __broadern_tuple_hash_aux {
898 static constexpr size_t hash(
const Tuple& tup) {
900 return __broadern_tuple_hash_aux<Tuple, Index - 1>::hash(tup) ^
901 _NEFORCE hash<ElementType>()(_NEFORCE
get<Index - 1>(tup));
904template <
typename Tuple>
905struct __broadern_tuple_hash_aux<Tuple, 1> {
906 static constexpr size_t hash(
const Tuple& tup) {
908 return _NEFORCE hash<ElementType>()(_NEFORCE
get<0>(tup));
911template <
typename Tuple>
912struct __broadern_tuple_hash_aux<Tuple, 0> {
913 static constexpr size_t hash(
const Tuple&) {
return 0; }
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
927 return inner::__broadern_tuple_hash_aux<Tuple,
sizeof...(Idx)>
::hash(tup);
931NEFORCE_END_NAMESPACE__
933#ifdef NEFORCE_STANDARD_17
935 template <
typename... Types>
936 struct tuple_size<_NEFORCE tuple<Types...>> : _NEFORCE integral_constant<_NEFORCE size_t, sizeof...(Types)> {};
938 template <_NEFORCE
size_t I,
typename... Types>
939 struct tuple_element<I, _NEFORCE tuple<Types...>> {
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
生成指定长度的索引序列
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移动赋值
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
比较两个空元组是否相等