1// -*- C++ -*-
2//===----------------------------------------------------------------------===//
3//
4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5// See https://llvm.org/LICENSE.txt for license information.
6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7//
8//===----------------------------------------------------------------------===//
9
10#ifndef _LIBCPP___TUPLE
11#define _LIBCPP___TUPLE
12
13#include <__config>
14#include <cstddef>
15#include <type_traits>
16
17#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
18#  pragma GCC system_header
19#  pragma clang include_instead(<tuple>)
20#  pragma clang include_instead(<utility>)
21#endif
22
23
24_LIBCPP_BEGIN_NAMESPACE_STD
25
26template <class _Tp> struct _LIBCPP_TEMPLATE_VIS tuple_size;
27
28#if !defined(_LIBCPP_CXX03_LANG)
29template <class _Tp, class...>
30using __enable_if_tuple_size_imp = _Tp;
31
32template <class _Tp>
33struct _LIBCPP_TEMPLATE_VIS tuple_size<__enable_if_tuple_size_imp<
34    const _Tp,
35    typename enable_if<!is_volatile<_Tp>::value>::type,
36    integral_constant<size_t, sizeof(tuple_size<_Tp>)>>>
37    : public integral_constant<size_t, tuple_size<_Tp>::value> {};
38
39template <class _Tp>
40struct _LIBCPP_TEMPLATE_VIS tuple_size<__enable_if_tuple_size_imp<
41    volatile _Tp,
42    typename enable_if<!is_const<_Tp>::value>::type,
43    integral_constant<size_t, sizeof(tuple_size<_Tp>)>>>
44    : public integral_constant<size_t, tuple_size<_Tp>::value> {};
45
46template <class _Tp>
47struct _LIBCPP_TEMPLATE_VIS tuple_size<__enable_if_tuple_size_imp<
48    const volatile _Tp,
49    integral_constant<size_t, sizeof(tuple_size<_Tp>)>>>
50    : public integral_constant<size_t, tuple_size<_Tp>::value> {};
51
52#else
53template <class _Tp> struct _LIBCPP_TEMPLATE_VIS tuple_size<const _Tp> : public tuple_size<_Tp> {};
54template <class _Tp> struct _LIBCPP_TEMPLATE_VIS tuple_size<volatile _Tp> : public tuple_size<_Tp> {};
55template <class _Tp> struct _LIBCPP_TEMPLATE_VIS tuple_size<const volatile _Tp> : public tuple_size<_Tp> {};
56#endif
57
58template <size_t _Ip, class _Tp> struct _LIBCPP_TEMPLATE_VIS tuple_element;
59
60template <size_t _Ip, class _Tp>
61struct _LIBCPP_TEMPLATE_VIS tuple_element<_Ip, const _Tp>
62{
63    typedef _LIBCPP_NODEBUG typename add_const<typename tuple_element<_Ip, _Tp>::type>::type type;
64};
65
66template <size_t _Ip, class _Tp>
67struct _LIBCPP_TEMPLATE_VIS tuple_element<_Ip, volatile _Tp>
68{
69    typedef _LIBCPP_NODEBUG typename add_volatile<typename tuple_element<_Ip, _Tp>::type>::type type;
70};
71
72template <size_t _Ip, class _Tp>
73struct _LIBCPP_TEMPLATE_VIS tuple_element<_Ip, const volatile _Tp>
74{
75    typedef _LIBCPP_NODEBUG typename add_cv<typename tuple_element<_Ip, _Tp>::type>::type type;
76};
77
78template <class _Tp> struct __tuple_like : false_type {};
79
80template <class _Tp> struct __tuple_like<const _Tp> : public __tuple_like<_Tp> {};
81template <class _Tp> struct __tuple_like<volatile _Tp> : public __tuple_like<_Tp> {};
82template <class _Tp> struct __tuple_like<const volatile _Tp> : public __tuple_like<_Tp> {};
83
84// tuple specializations
85
86#ifndef _LIBCPP_CXX03_LANG
87
88template <size_t...> struct __tuple_indices {};
89
90template <class _IdxType, _IdxType... _Values>
91struct __integer_sequence {
92  template <template <class _OIdxType, _OIdxType...> class _ToIndexSeq, class _ToIndexType>
93  using __convert = _ToIndexSeq<_ToIndexType, _Values...>;
94
95  template <size_t _Sp>
96  using __to_tuple_indices = __tuple_indices<(_Values + _Sp)...>;
97};
98
99#if !__has_builtin(__make_integer_seq) || defined(_LIBCPP_TESTING_FALLBACK_MAKE_INTEGER_SEQUENCE)
100namespace __detail {
101
102template<typename _Tp, size_t ..._Extra> struct __repeat;
103template<typename _Tp, _Tp ..._Np, size_t ..._Extra> struct __repeat<__integer_sequence<_Tp, _Np...>, _Extra...> {
104  typedef _LIBCPP_NODEBUG __integer_sequence<_Tp,
105                           _Np...,
106                           sizeof...(_Np) + _Np...,
107                           2 * sizeof...(_Np) + _Np...,
108                           3 * sizeof...(_Np) + _Np...,
109                           4 * sizeof...(_Np) + _Np...,
110                           5 * sizeof...(_Np) + _Np...,
111                           6 * sizeof...(_Np) + _Np...,
112                           7 * sizeof...(_Np) + _Np...,
113                           _Extra...> type;
114};
115
116template<size_t _Np> struct __parity;
117template<size_t _Np> struct __make : __parity<_Np % 8>::template __pmake<_Np> {};
118
119template<> struct __make<0> { typedef __integer_sequence<size_t> type; };
120template<> struct __make<1> { typedef __integer_sequence<size_t, 0> type; };
121template<> struct __make<2> { typedef __integer_sequence<size_t, 0, 1> type; };
122template<> struct __make<3> { typedef __integer_sequence<size_t, 0, 1, 2> type; };
123template<> struct __make<4> { typedef __integer_sequence<size_t, 0, 1, 2, 3> type; };
124template<> struct __make<5> { typedef __integer_sequence<size_t, 0, 1, 2, 3, 4> type; };
125template<> struct __make<6> { typedef __integer_sequence<size_t, 0, 1, 2, 3, 4, 5> type; };
126template<> struct __make<7> { typedef __integer_sequence<size_t, 0, 1, 2, 3, 4, 5, 6> type; };
127
128template<> struct __parity<0> { template<size_t _Np> struct __pmake : __repeat<typename __make<_Np / 8>::type> {}; };
129template<> struct __parity<1> { template<size_t _Np> struct __pmake : __repeat<typename __make<_Np / 8>::type, _Np - 1> {}; };
130template<> struct __parity<2> { template<size_t _Np> struct __pmake : __repeat<typename __make<_Np / 8>::type, _Np - 2, _Np - 1> {}; };
131template<> struct __parity<3> { template<size_t _Np> struct __pmake : __repeat<typename __make<_Np / 8>::type, _Np - 3, _Np - 2, _Np - 1> {}; };
132template<> struct __parity<4> { template<size_t _Np> struct __pmake : __repeat<typename __make<_Np / 8>::type, _Np - 4, _Np - 3, _Np - 2, _Np - 1> {}; };
133template<> struct __parity<5> { template<size_t _Np> struct __pmake : __repeat<typename __make<_Np / 8>::type, _Np - 5, _Np - 4, _Np - 3, _Np - 2, _Np - 1> {}; };
134template<> struct __parity<6> { template<size_t _Np> struct __pmake : __repeat<typename __make<_Np / 8>::type, _Np - 6, _Np - 5, _Np - 4, _Np - 3, _Np - 2, _Np - 1> {}; };
135template<> struct __parity<7> { template<size_t _Np> struct __pmake : __repeat<typename __make<_Np / 8>::type, _Np - 7, _Np - 6, _Np - 5, _Np - 4, _Np - 3, _Np - 2, _Np - 1> {}; };
136
137} // namespace detail
138
139#endif // !__has_builtin(__make_integer_seq) || defined(_LIBCPP_TESTING_FALLBACK_MAKE_INTEGER_SEQUENCE)
140
141#if __has_builtin(__make_integer_seq)
142template <size_t _Ep, size_t _Sp>
143using __make_indices_imp =
144    typename __make_integer_seq<__integer_sequence, size_t, _Ep - _Sp>::template
145    __to_tuple_indices<_Sp>;
146#else
147template <size_t _Ep, size_t _Sp>
148using __make_indices_imp =
149    typename __detail::__make<_Ep - _Sp>::type::template __to_tuple_indices<_Sp>;
150
151#endif
152
153template <size_t _Ep, size_t _Sp = 0>
154struct __make_tuple_indices
155{
156    static_assert(_Sp <= _Ep, "__make_tuple_indices input error");
157    typedef __make_indices_imp<_Ep, _Sp> type;
158};
159
160
161template <class ..._Tp> class _LIBCPP_TEMPLATE_VIS tuple;
162
163template <class... _Tp> struct __tuple_like<tuple<_Tp...> > : true_type {};
164
165template <class ..._Tp>
166struct _LIBCPP_TEMPLATE_VIS tuple_size<tuple<_Tp...> >
167    : public integral_constant<size_t, sizeof...(_Tp)>
168{
169};
170
171template <size_t _Ip, class ..._Tp>
172_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
173typename tuple_element<_Ip, tuple<_Tp...> >::type&
174get(tuple<_Tp...>&) _NOEXCEPT;
175
176template <size_t _Ip, class ..._Tp>
177_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
178const typename tuple_element<_Ip, tuple<_Tp...> >::type&
179get(const tuple<_Tp...>&) _NOEXCEPT;
180
181template <size_t _Ip, class ..._Tp>
182_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
183typename tuple_element<_Ip, tuple<_Tp...> >::type&&
184get(tuple<_Tp...>&&) _NOEXCEPT;
185
186template <size_t _Ip, class ..._Tp>
187_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
188const typename tuple_element<_Ip, tuple<_Tp...> >::type&&
189get(const tuple<_Tp...>&&) _NOEXCEPT;
190
191#endif // !defined(_LIBCPP_CXX03_LANG)
192
193// pair specializations
194
195template <class _T1, class _T2> struct __tuple_like<pair<_T1, _T2> > : true_type {};
196
197template <size_t _Ip, class _T1, class _T2>
198_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
199typename tuple_element<_Ip, pair<_T1, _T2> >::type&
200get(pair<_T1, _T2>&) _NOEXCEPT;
201
202template <size_t _Ip, class _T1, class _T2>
203_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
204const typename tuple_element<_Ip, pair<_T1, _T2> >::type&
205get(const pair<_T1, _T2>&) _NOEXCEPT;
206
207#ifndef _LIBCPP_CXX03_LANG
208template <size_t _Ip, class _T1, class _T2>
209_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
210typename tuple_element<_Ip, pair<_T1, _T2> >::type&&
211get(pair<_T1, _T2>&&) _NOEXCEPT;
212
213template <size_t _Ip, class _T1, class _T2>
214_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
215const typename tuple_element<_Ip, pair<_T1, _T2> >::type&&
216get(const pair<_T1, _T2>&&) _NOEXCEPT;
217#endif
218
219// array specializations
220
221template <class _Tp, size_t _Size> struct _LIBCPP_TEMPLATE_VIS array;
222
223template <class _Tp, size_t _Size> struct __tuple_like<array<_Tp, _Size> > : true_type {};
224
225template <size_t _Ip, class _Tp, size_t _Size>
226_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
227_Tp&
228get(array<_Tp, _Size>&) _NOEXCEPT;
229
230template <size_t _Ip, class _Tp, size_t _Size>
231_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
232const _Tp&
233get(const array<_Tp, _Size>&) _NOEXCEPT;
234
235#ifndef _LIBCPP_CXX03_LANG
236template <size_t _Ip, class _Tp, size_t _Size>
237_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
238_Tp&&
239get(array<_Tp, _Size>&&) _NOEXCEPT;
240
241template <size_t _Ip, class _Tp, size_t _Size>
242_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
243const _Tp&&
244get(const array<_Tp, _Size>&&) _NOEXCEPT;
245#endif
246
247#ifndef _LIBCPP_CXX03_LANG
248
249// __tuple_types
250
251template <class ..._Tp> struct __tuple_types {};
252
253#if !__has_builtin(__type_pack_element)
254
255namespace __indexer_detail {
256
257template <size_t _Idx, class _Tp>
258struct __indexed { using type _LIBCPP_NODEBUG = _Tp; };
259
260template <class _Types, class _Indexes> struct __indexer;
261
262template <class ..._Types, size_t ..._Idx>
263struct __indexer<__tuple_types<_Types...>, __tuple_indices<_Idx...>>
264    : __indexed<_Idx, _Types>...
265{};
266
267template <size_t _Idx, class _Tp>
268__indexed<_Idx, _Tp> __at_index(__indexed<_Idx, _Tp> const&);
269
270} // namespace __indexer_detail
271
272template <size_t _Idx, class ..._Types>
273using __type_pack_element _LIBCPP_NODEBUG = typename decltype(
274    __indexer_detail::__at_index<_Idx>(
275        __indexer_detail::__indexer<
276            __tuple_types<_Types...>,
277            typename __make_tuple_indices<sizeof...(_Types)>::type
278        >{})
279  )::type;
280#endif
281
282template <size_t _Ip, class ..._Types>
283struct _LIBCPP_TEMPLATE_VIS tuple_element<_Ip, __tuple_types<_Types...> >
284{
285    static_assert(_Ip < sizeof...(_Types), "tuple_element index out of range");
286    typedef _LIBCPP_NODEBUG __type_pack_element<_Ip, _Types...> type;
287};
288
289
290template <class ..._Tp>
291struct _LIBCPP_TEMPLATE_VIS tuple_size<__tuple_types<_Tp...> >
292    : public integral_constant<size_t, sizeof...(_Tp)>
293{
294};
295
296template <class... _Tp> struct __tuple_like<__tuple_types<_Tp...> > : true_type {};
297
298template <bool _ApplyLV, bool _ApplyConst, bool _ApplyVolatile>
299struct __apply_cv_mf;
300template <>
301struct __apply_cv_mf<false, false, false> {
302  template <class _Tp> using __apply = _Tp;
303};
304template <>
305struct __apply_cv_mf<false, true, false> {
306  template <class _Tp> using __apply _LIBCPP_NODEBUG = const _Tp;
307};
308template <>
309struct __apply_cv_mf<false, false, true> {
310  template <class _Tp> using __apply _LIBCPP_NODEBUG = volatile _Tp;
311};
312template <>
313struct __apply_cv_mf<false, true, true> {
314  template <class _Tp> using __apply _LIBCPP_NODEBUG = const volatile _Tp;
315};
316template <>
317struct __apply_cv_mf<true, false, false> {
318  template <class _Tp> using __apply _LIBCPP_NODEBUG = _Tp&;
319};
320template <>
321struct __apply_cv_mf<true, true, false> {
322  template <class _Tp> using __apply _LIBCPP_NODEBUG = const _Tp&;
323};
324template <>
325struct __apply_cv_mf<true, false, true> {
326  template <class _Tp> using __apply _LIBCPP_NODEBUG = volatile _Tp&;
327};
328template <>
329struct __apply_cv_mf<true, true, true> {
330  template <class _Tp> using __apply _LIBCPP_NODEBUG = const volatile _Tp&;
331};
332template <class _Tp, class _RawTp = typename remove_reference<_Tp>::type>
333using __apply_cv_t _LIBCPP_NODEBUG = __apply_cv_mf<
334    is_lvalue_reference<_Tp>::value,
335    is_const<_RawTp>::value,
336    is_volatile<_RawTp>::value>;
337
338// __make_tuple_types
339
340// __make_tuple_types<_Tuple<_Types...>, _Ep, _Sp>::type is a
341// __tuple_types<_Types...> using only those _Types in the range [_Sp, _Ep).
342// _Sp defaults to 0 and _Ep defaults to tuple_size<_Tuple>.  If _Tuple is a
343// lvalue_reference type, then __tuple_types<_Types&...> is the result.
344
345template <class _TupleTypes, class _TupleIndices>
346struct __make_tuple_types_flat;
347
348template <template <class...> class _Tuple, class ..._Types, size_t ..._Idx>
349struct __make_tuple_types_flat<_Tuple<_Types...>, __tuple_indices<_Idx...>> {
350  // Specialization for pair, tuple, and __tuple_types
351  template <class _Tp, class _ApplyFn = __apply_cv_t<_Tp>>
352  using __apply_quals _LIBCPP_NODEBUG = __tuple_types<
353      typename _ApplyFn::template __apply<__type_pack_element<_Idx, _Types...>>...
354    >;
355};
356
357template <class _Vt, size_t _Np, size_t ..._Idx>
358struct __make_tuple_types_flat<array<_Vt, _Np>, __tuple_indices<_Idx...>> {
359  template <size_t>
360  using __value_type = _Vt;
361  template <class _Tp, class _ApplyFn = __apply_cv_t<_Tp>>
362  using __apply_quals = __tuple_types<
363      typename _ApplyFn::template __apply<__value_type<_Idx>>...
364    >;
365};
366
367template <class _Tp, size_t _Ep = tuple_size<typename remove_reference<_Tp>::type>::value,
368          size_t _Sp = 0,
369          bool _SameSize = (_Ep == tuple_size<typename remove_reference<_Tp>::type>::value)>
370struct __make_tuple_types
371{
372    static_assert(_Sp <= _Ep, "__make_tuple_types input error");
373    using _RawTp = typename remove_cv<typename remove_reference<_Tp>::type>::type;
374    using _Maker = __make_tuple_types_flat<_RawTp, typename __make_tuple_indices<_Ep, _Sp>::type>;
375    using type = typename _Maker::template __apply_quals<_Tp>;
376};
377
378template <class ..._Types, size_t _Ep>
379struct __make_tuple_types<tuple<_Types...>, _Ep, 0, true> {
380  typedef _LIBCPP_NODEBUG __tuple_types<_Types...> type;
381};
382
383template <class ..._Types, size_t _Ep>
384struct __make_tuple_types<__tuple_types<_Types...>, _Ep, 0, true> {
385  typedef _LIBCPP_NODEBUG __tuple_types<_Types...> type;
386};
387
388template <bool ..._Preds>
389struct __all_dummy;
390
391template <bool ..._Pred>
392struct __all : _IsSame<__all_dummy<_Pred...>, __all_dummy<((void)_Pred, true)...>> {};
393
394struct __tuple_sfinae_base {
395  template <template <class, class...> class _Trait,
396            class ..._LArgs, class ..._RArgs>
397  static auto __do_test(__tuple_types<_LArgs...>, __tuple_types<_RArgs...>)
398    -> __all<typename enable_if<_Trait<_LArgs, _RArgs>::value, bool>::type{true}...>;
399  template <template <class...> class>
400  static auto __do_test(...) -> false_type;
401
402  template <class _FromArgs, class _ToArgs>
403  using __constructible = decltype(__do_test<is_constructible>(_ToArgs{}, _FromArgs{}));
404  template <class _FromArgs, class _ToArgs>
405  using __convertible = decltype(__do_test<is_convertible>(_FromArgs{}, _ToArgs{}));
406  template <class _FromArgs, class _ToArgs>
407  using __assignable = decltype(__do_test<is_assignable>(_ToArgs{}, _FromArgs{}));
408};
409
410// __tuple_convertible
411
412template <class _Tp, class _Up, bool = __tuple_like<typename remove_reference<_Tp>::type>::value,
413                                bool = __tuple_like<_Up>::value>
414struct __tuple_convertible
415    : public false_type {};
416
417template <class _Tp, class _Up>
418struct __tuple_convertible<_Tp, _Up, true, true>
419    : public __tuple_sfinae_base::__convertible<
420      typename __make_tuple_types<_Tp>::type
421    , typename __make_tuple_types<_Up>::type
422    >
423{};
424
425// __tuple_constructible
426
427template <class _Tp, class _Up, bool = __tuple_like<typename remove_reference<_Tp>::type>::value,
428                                bool = __tuple_like<_Up>::value>
429struct __tuple_constructible
430    : public false_type {};
431
432template <class _Tp, class _Up>
433struct __tuple_constructible<_Tp, _Up, true, true>
434    : public __tuple_sfinae_base::__constructible<
435      typename __make_tuple_types<_Tp>::type
436    , typename __make_tuple_types<_Up>::type
437    >
438{};
439
440// __tuple_assignable
441
442template <class _Tp, class _Up, bool = __tuple_like<typename remove_reference<_Tp>::type>::value,
443                                bool = __tuple_like<_Up>::value>
444struct __tuple_assignable
445    : public false_type {};
446
447template <class _Tp, class _Up>
448struct __tuple_assignable<_Tp, _Up, true, true>
449    : public __tuple_sfinae_base::__assignable<
450      typename __make_tuple_types<_Tp>::type
451    , typename __make_tuple_types<_Up&>::type
452    >
453{};
454
455
456template <size_t _Ip, class ..._Tp>
457struct _LIBCPP_TEMPLATE_VIS tuple_element<_Ip, tuple<_Tp...> >
458{
459    typedef _LIBCPP_NODEBUG typename tuple_element<_Ip, __tuple_types<_Tp...> >::type type;
460};
461
462#if _LIBCPP_STD_VER > 11
463template <size_t _Ip, class ..._Tp>
464using tuple_element_t _LIBCPP_NODEBUG = typename tuple_element <_Ip, _Tp...>::type;
465#endif
466
467template <bool _IsTuple, class _SizeTrait, size_t _Expected>
468struct __tuple_like_with_size_imp : false_type {};
469
470template <class _SizeTrait, size_t _Expected>
471struct __tuple_like_with_size_imp<true, _SizeTrait, _Expected>
472    : integral_constant<bool, _SizeTrait::value == _Expected> {};
473
474template <class _Tuple, size_t _ExpectedSize, class _RawTuple = __uncvref_t<_Tuple> >
475using __tuple_like_with_size _LIBCPP_NODEBUG = __tuple_like_with_size_imp<
476                                   __tuple_like<_RawTuple>::value,
477                                   tuple_size<_RawTuple>, _ExpectedSize
478                              >;
479
480struct _LIBCPP_TYPE_VIS __check_tuple_constructor_fail {
481
482    static constexpr bool __enable_explicit_default() { return false; }
483    static constexpr bool __enable_implicit_default() { return false; }
484    template <class ...>
485    static constexpr bool __enable_explicit() { return false; }
486    template <class ...>
487    static constexpr bool __enable_implicit() { return false; }
488    template <class ...>
489    static constexpr bool __enable_assign() { return false; }
490};
491#endif // !defined(_LIBCPP_CXX03_LANG)
492
493#if _LIBCPP_STD_VER > 14
494
495template <bool _CanCopy, bool _CanMove>
496struct __sfinae_ctor_base {};
497template <>
498struct __sfinae_ctor_base<false, false> {
499  __sfinae_ctor_base() = default;
500  __sfinae_ctor_base(__sfinae_ctor_base const&) = delete;
501  __sfinae_ctor_base(__sfinae_ctor_base &&) = delete;
502  __sfinae_ctor_base& operator=(__sfinae_ctor_base const&) = default;
503  __sfinae_ctor_base& operator=(__sfinae_ctor_base&&) = default;
504};
505template <>
506struct __sfinae_ctor_base<true, false> {
507  __sfinae_ctor_base() = default;
508  __sfinae_ctor_base(__sfinae_ctor_base const&) = default;
509  __sfinae_ctor_base(__sfinae_ctor_base &&) = delete;
510  __sfinae_ctor_base& operator=(__sfinae_ctor_base const&) = default;
511  __sfinae_ctor_base& operator=(__sfinae_ctor_base&&) = default;
512};
513template <>
514struct __sfinae_ctor_base<false, true> {
515  __sfinae_ctor_base() = default;
516  __sfinae_ctor_base(__sfinae_ctor_base const&) = delete;
517  __sfinae_ctor_base(__sfinae_ctor_base &&) = default;
518  __sfinae_ctor_base& operator=(__sfinae_ctor_base const&) = default;
519  __sfinae_ctor_base& operator=(__sfinae_ctor_base&&) = default;
520};
521
522template <bool _CanCopy, bool _CanMove>
523struct __sfinae_assign_base {};
524template <>
525struct __sfinae_assign_base<false, false> {
526  __sfinae_assign_base() = default;
527  __sfinae_assign_base(__sfinae_assign_base const&) = default;
528  __sfinae_assign_base(__sfinae_assign_base &&) = default;
529  __sfinae_assign_base& operator=(__sfinae_assign_base const&) = delete;
530  __sfinae_assign_base& operator=(__sfinae_assign_base&&) = delete;
531};
532template <>
533struct __sfinae_assign_base<true, false> {
534  __sfinae_assign_base() = default;
535  __sfinae_assign_base(__sfinae_assign_base const&) = default;
536  __sfinae_assign_base(__sfinae_assign_base &&) = default;
537  __sfinae_assign_base& operator=(__sfinae_assign_base const&) = default;
538  __sfinae_assign_base& operator=(__sfinae_assign_base&&) = delete;
539};
540template <>
541struct __sfinae_assign_base<false, true> {
542  __sfinae_assign_base() = default;
543  __sfinae_assign_base(__sfinae_assign_base const&) = default;
544  __sfinae_assign_base(__sfinae_assign_base &&) = default;
545  __sfinae_assign_base& operator=(__sfinae_assign_base const&) = delete;
546  __sfinae_assign_base& operator=(__sfinae_assign_base&&) = default;
547};
548#endif // _LIBCPP_STD_VER > 14
549
550_LIBCPP_END_NAMESPACE_STD
551
552#endif // _LIBCPP___TUPLE
553