[libc++] Refactor __tuple_like and __pair_like (#85206)
The exposition-only type trait `pair-like` includes `ranges::subrange`, but in every single case excludes `ranges::subrange` from the list. This patch introduces two new traits `__tuple_like_no_subrange` and `__pair_like_no_subrange`, which exclude `ranges::subrange` from the possible matches. `__pair_like` is no longer required, and thus removed. `__tuple_like` is implemented as `__tuple_like_no_subrange` or a `ranges::subrange` specialization.
This commit is contained in:
@@ -709,12 +709,12 @@ set(files
|
||||
__tree
|
||||
__tuple/find_index.h
|
||||
__tuple/make_tuple_types.h
|
||||
__tuple/pair_like.h
|
||||
__tuple/sfinae_helpers.h
|
||||
__tuple/tuple_element.h
|
||||
__tuple/tuple_indices.h
|
||||
__tuple/tuple_like.h
|
||||
__tuple/tuple_like_ext.h
|
||||
__tuple/tuple_like_no_subrange.h
|
||||
__tuple/tuple_size.h
|
||||
__tuple/tuple_types.h
|
||||
__type_traits/add_const.h
|
||||
|
||||
@@ -18,10 +18,12 @@
|
||||
#include <__type_traits/invoke.h>
|
||||
#include <__type_traits/is_constant_evaluated.h>
|
||||
#include <__type_traits/is_equality_comparable.h>
|
||||
#include <__type_traits/is_integral.h>
|
||||
#include <__type_traits/operation_traits.h>
|
||||
#include <__utility/move.h>
|
||||
#include <__utility/pair.h>
|
||||
#include <__utility/unreachable.h>
|
||||
#include <cstddef>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
# pragma GCC system_header
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
#include <__config>
|
||||
#include <__memory/construct_at.h>
|
||||
#include <__memory/uses_allocator.h>
|
||||
#include <__tuple/pair_like.h>
|
||||
#include <__tuple/tuple_like_no_subrange.h>
|
||||
#include <__type_traits/enable_if.h>
|
||||
#include <__type_traits/is_same.h>
|
||||
#include <__type_traits/remove_cv.h>
|
||||
@@ -128,11 +128,7 @@ __uses_allocator_construction_args(const _Alloc& __alloc, const pair<_Up, _Vp>&&
|
||||
std::forward_as_tuple(std::get<1>(std::move(__pair))));
|
||||
}
|
||||
|
||||
template < class _Pair,
|
||||
class _Alloc,
|
||||
__pair_like _PairLike,
|
||||
__enable_if_t<__is_cv_std_pair<_Pair> && !__is_specialization_of_subrange<remove_cvref_t<_PairLike>>::value,
|
||||
int> = 0>
|
||||
template <class _Pair, class _Alloc, __pair_like_no_subrange _PairLike, __enable_if_t<__is_cv_std_pair<_Pair>, int> = 0>
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr auto
|
||||
__uses_allocator_construction_args(const _Alloc& __alloc, _PairLike&& __p) noexcept {
|
||||
return std::__uses_allocator_construction_args<_Pair>(
|
||||
@@ -161,9 +157,7 @@ inline constexpr bool __convertible_to_const_pair_ref =
|
||||
# if _LIBCPP_STD_VER >= 23
|
||||
template <class _Tp, class _Up>
|
||||
inline constexpr bool __uses_allocator_constraints =
|
||||
__is_cv_std_pair<_Tp> &&
|
||||
(__is_specialization_of_subrange<remove_cvref_t<_Up>>::value ||
|
||||
(!__pair_like<_Up> && !__convertible_to_const_pair_ref<_Up>));
|
||||
__is_cv_std_pair<_Tp> && !__pair_like_no_subrange<_Up> && !__convertible_to_const_pair_ref<_Up>;
|
||||
# else
|
||||
template <class _Tp, class _Up>
|
||||
inline constexpr bool __uses_allocator_constraints = __is_cv_std_pair<_Tp> && !__convertible_to_const_pair_ref<_Up>;
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <__assert>
|
||||
#include <__availability>
|
||||
#include <__config>
|
||||
#include <__fwd/pair.h>
|
||||
#include <__memory_resource/memory_resource.h>
|
||||
#include <__utility/exception_guard.h>
|
||||
#include <cstddef>
|
||||
|
||||
@@ -28,8 +28,8 @@
|
||||
#include <__ranges/enable_borrowed_range.h>
|
||||
#include <__ranges/size.h>
|
||||
#include <__ranges/view_interface.h>
|
||||
#include <__tuple/pair_like.h>
|
||||
#include <__tuple/tuple_element.h>
|
||||
#include <__tuple/tuple_like_no_subrange.h>
|
||||
#include <__tuple/tuple_size.h>
|
||||
#include <__type_traits/conditional.h>
|
||||
#include <__type_traits/decay.h>
|
||||
@@ -64,7 +64,7 @@ concept __convertible_to_non_slicing =
|
||||
|
||||
template <class _Pair, class _Iter, class _Sent>
|
||||
concept __pair_like_convertible_from =
|
||||
!range<_Pair> && __pair_like<_Pair> && constructible_from<_Pair, _Iter, _Sent> &&
|
||||
!range<_Pair> && __pair_like_no_subrange<_Pair> && constructible_from<_Pair, _Iter, _Sent> &&
|
||||
__convertible_to_non_slicing<_Iter, tuple_element_t<0, _Pair>> && convertible_to<_Sent, tuple_element_t<1, _Pair>>;
|
||||
|
||||
template <input_or_output_iterator _Iter,
|
||||
@@ -125,8 +125,7 @@ public:
|
||||
requires(_Kind == subrange_kind::sized)
|
||||
: subrange(ranges::begin(__range), ranges::end(__range), __n) {}
|
||||
|
||||
template <__different_from<subrange> _Pair>
|
||||
requires __pair_like_convertible_from<_Pair, const _Iter&, const _Sent&>
|
||||
template <__pair_like_convertible_from<const _Iter&, const _Sent&> _Pair>
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr operator _Pair() const {
|
||||
return _Pair(__begin_, __end_);
|
||||
}
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _LIBCPP___TUPLE_PAIR_LIKE_H
|
||||
#define _LIBCPP___TUPLE_PAIR_LIKE_H
|
||||
|
||||
#include <__config>
|
||||
#include <__tuple/tuple_like.h>
|
||||
#include <__tuple/tuple_size.h>
|
||||
#include <__type_traits/remove_cvref.h>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
# pragma GCC system_header
|
||||
#endif
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
#if _LIBCPP_STD_VER >= 20
|
||||
|
||||
template <class _Tp>
|
||||
concept __pair_like = __tuple_like<_Tp> && tuple_size<remove_cvref_t<_Tp>>::value == 2;
|
||||
|
||||
#endif // _LIBCPP_STD_VER >= 20
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCPP___TUPLE_PAIR_LIKE_H
|
||||
@@ -10,12 +10,9 @@
|
||||
#define _LIBCPP___TUPLE_TUPLE_LIKE_H
|
||||
|
||||
#include <__config>
|
||||
#include <__fwd/array.h>
|
||||
#include <__fwd/complex.h>
|
||||
#include <__fwd/pair.h>
|
||||
#include <__fwd/subrange.h>
|
||||
#include <__fwd/tuple.h>
|
||||
#include <__type_traits/integral_constant.h>
|
||||
#include <__tuple/tuple_like_no_subrange.h>
|
||||
#include <__tuple/tuple_size.h>
|
||||
#include <__type_traits/remove_cvref.h>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
@@ -27,29 +24,16 @@ _LIBCPP_BEGIN_NAMESPACE_STD
|
||||
#if _LIBCPP_STD_VER >= 20
|
||||
|
||||
template <class _Tp>
|
||||
struct __tuple_like_impl : false_type {};
|
||||
inline constexpr bool __is_ranges_subrange_v = false;
|
||||
|
||||
template <class... _Tp>
|
||||
struct __tuple_like_impl<tuple<_Tp...> > : true_type {};
|
||||
|
||||
template <class _T1, class _T2>
|
||||
struct __tuple_like_impl<pair<_T1, _T2> > : true_type {};
|
||||
|
||||
template <class _Tp, size_t _Size>
|
||||
struct __tuple_like_impl<array<_Tp, _Size> > : true_type {};
|
||||
|
||||
template <class _Ip, class _Sp, ranges::subrange_kind _Kp>
|
||||
struct __tuple_like_impl<ranges::subrange<_Ip, _Sp, _Kp> > : true_type {};
|
||||
|
||||
# if _LIBCPP_STD_VER >= 26
|
||||
template <class _Iter, class _Sent, ranges::subrange_kind _Kind>
|
||||
inline constexpr bool __is_ranges_subrange_v<ranges::subrange<_Iter, _Sent, _Kind>> = true;
|
||||
|
||||
template <class _Tp>
|
||||
struct __tuple_like_impl<complex<_Tp>> : true_type {};
|
||||
concept __tuple_like = __tuple_like_no_subrange<_Tp> || __is_ranges_subrange_v<remove_cvref_t<_Tp>>;
|
||||
|
||||
# endif
|
||||
|
||||
template <class _Tp>
|
||||
concept __tuple_like = __tuple_like_impl<remove_cvref_t<_Tp>>::value;
|
||||
// As of writing this comment every use of `pair-like` in the standard excludes `ranges::subrange`, so
|
||||
// you most likely want to use `__pair_like_no_subrange` if you're looking for `pair-like`.
|
||||
|
||||
#endif // _LIBCPP_STD_VER >= 20
|
||||
|
||||
|
||||
61
libcxx/include/__tuple/tuple_like_no_subrange.h
Normal file
61
libcxx/include/__tuple/tuple_like_no_subrange.h
Normal file
@@ -0,0 +1,61 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _LIBCPP___TUPLE_TUPLE_LIKE_NO_SUBRANGE_H
|
||||
#define _LIBCPP___TUPLE_TUPLE_LIKE_NO_SUBRANGE_H
|
||||
|
||||
#include <__config>
|
||||
#include <__fwd/array.h>
|
||||
#include <__fwd/complex.h>
|
||||
#include <__fwd/pair.h>
|
||||
#include <__fwd/tuple.h>
|
||||
#include <__tuple/tuple_size.h>
|
||||
#include <__type_traits/remove_cvref.h>
|
||||
#include <cstddef>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
# pragma GCC system_header
|
||||
#endif
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
#if _LIBCPP_STD_VER >= 20
|
||||
|
||||
template <class _Tp>
|
||||
inline constexpr bool __tuple_like_no_subrange_impl = false;
|
||||
|
||||
template <class... _Tp>
|
||||
inline constexpr bool __tuple_like_no_subrange_impl<tuple<_Tp...>> = true;
|
||||
|
||||
template <class _T1, class _T2>
|
||||
inline constexpr bool __tuple_like_no_subrange_impl<pair<_T1, _T2>> = true;
|
||||
|
||||
template <class _Tp, size_t _Size>
|
||||
inline constexpr bool __tuple_like_no_subrange_impl<array<_Tp, _Size>> = true;
|
||||
|
||||
# if _LIBCPP_STD_VER >= 26
|
||||
|
||||
template <class _Tp>
|
||||
inline constexpr bool __tuple_like_no_subrange_impl<complex<_Tp>> = true;
|
||||
|
||||
# endif
|
||||
|
||||
template <class _Tp>
|
||||
concept __tuple_like_no_subrange = __tuple_like_no_subrange_impl<remove_cvref_t<_Tp>>;
|
||||
|
||||
// This is equivalent to the exposition-only type trait `pair-like`, except that it is false for specializations of
|
||||
// `ranges::subrange`. This is more useful than the pair-like concept in the standard because every use of `pair-like`
|
||||
// excludes `ranges::subrange`.
|
||||
template <class _Tp>
|
||||
concept __pair_like_no_subrange = __tuple_like_no_subrange<_Tp> && tuple_size<remove_cvref_t<_Tp>>::value == 2;
|
||||
|
||||
#endif // _LIBCPP_STD_VER >= 20
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCPP___TUPLE_TUPLE_LIKE_NO_SUBRANGE_H
|
||||
@@ -15,12 +15,11 @@
|
||||
#include <__config>
|
||||
#include <__fwd/array.h>
|
||||
#include <__fwd/pair.h>
|
||||
#include <__fwd/subrange.h>
|
||||
#include <__fwd/tuple.h>
|
||||
#include <__tuple/pair_like.h>
|
||||
#include <__tuple/sfinae_helpers.h>
|
||||
#include <__tuple/tuple_element.h>
|
||||
#include <__tuple/tuple_indices.h>
|
||||
#include <__tuple/tuple_like_no_subrange.h>
|
||||
#include <__tuple/tuple_size.h>
|
||||
#include <__type_traits/common_reference.h>
|
||||
#include <__type_traits/common_type.h>
|
||||
@@ -60,14 +59,6 @@ struct __non_trivially_copyable_base {
|
||||
__non_trivially_copyable_base(__non_trivially_copyable_base const&) _NOEXCEPT {}
|
||||
};
|
||||
|
||||
#if _LIBCPP_STD_VER >= 23
|
||||
template <class _Tp>
|
||||
struct __is_specialization_of_subrange : false_type {};
|
||||
|
||||
template <class _Iter, class _Sent, ranges::subrange_kind _Kind>
|
||||
struct __is_specialization_of_subrange<ranges::subrange<_Iter, _Sent, _Kind>> : true_type {};
|
||||
#endif
|
||||
|
||||
template <class _T1, class _T2>
|
||||
struct _LIBCPP_TEMPLATE_VIS pair
|
||||
#if defined(_LIBCPP_DEPRECATED_ABI_DISABLE_PAIR_TRIVIAL_COPY_CTOR)
|
||||
@@ -201,19 +192,19 @@ struct _LIBCPP_TEMPLATE_VIS pair
|
||||
# endif
|
||||
|
||||
# if _LIBCPP_STD_VER >= 23
|
||||
// TODO: Remove this workaround in LLVM 20. The bug got fixed in Clang 18.
|
||||
// This is a workaround for http://llvm.org/PR60710. We should be able to remove it once Clang is fixed.
|
||||
template <class _PairLike>
|
||||
_LIBCPP_HIDE_FROM_ABI static constexpr bool __pair_like_explicit_wknd() {
|
||||
if constexpr (__pair_like<_PairLike>) {
|
||||
if constexpr (__pair_like_no_subrange<_PairLike>) {
|
||||
return !is_convertible_v<decltype(std::get<0>(std::declval<_PairLike&&>())), first_type> ||
|
||||
!is_convertible_v<decltype(std::get<1>(std::declval<_PairLike&&>())), second_type>;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <__pair_like _PairLike>
|
||||
requires(!__is_specialization_of_subrange<remove_cvref_t<_PairLike>>::value &&
|
||||
is_constructible_v<first_type, decltype(std::get<0>(std::declval<_PairLike &&>()))> &&
|
||||
template <__pair_like_no_subrange _PairLike>
|
||||
requires(is_constructible_v<first_type, decltype(std::get<0>(std::declval<_PairLike &&>()))> &&
|
||||
is_constructible_v<second_type, decltype(std::get<1>(std::declval<_PairLike &&>()))>)
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit(__pair_like_explicit_wknd<_PairLike>()) pair(_PairLike&& __p)
|
||||
: first(std::get<0>(std::forward<_PairLike>(__p))), second(std::get<1>(std::forward<_PairLike>(__p))) {}
|
||||
@@ -306,8 +297,8 @@ struct _LIBCPP_TEMPLATE_VIS pair
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <__pair_like _PairLike>
|
||||
requires(__different_from<_PairLike, pair> && !__is_specialization_of_subrange<remove_cvref_t<_PairLike>>::value &&
|
||||
template <__pair_like_no_subrange _PairLike>
|
||||
requires(__different_from<_PairLike, pair> &&
|
||||
is_assignable_v<first_type&, decltype(std::get<0>(std::declval<_PairLike>()))> &&
|
||||
is_assignable_v<second_type&, decltype(std::get<1>(std::declval<_PairLike>()))>)
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr pair& operator=(_PairLike&& __p) {
|
||||
@@ -316,8 +307,8 @@ struct _LIBCPP_TEMPLATE_VIS pair
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <__pair_like _PairLike>
|
||||
requires(__different_from<_PairLike, pair> && !__is_specialization_of_subrange<remove_cvref_t<_PairLike>>::value &&
|
||||
template <__pair_like_no_subrange _PairLike>
|
||||
requires(__different_from<_PairLike, pair> &&
|
||||
is_assignable_v<first_type const&, decltype(std::get<0>(std::declval<_PairLike>()))> &&
|
||||
is_assignable_v<second_type const&, decltype(std::get<1>(std::declval<_PairLike>()))>)
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr pair const& operator=(_PairLike&& __p) const {
|
||||
|
||||
@@ -705,12 +705,12 @@
|
||||
{ include: [ "<__thread/timed_backoff_policy.h>", "private", "<thread>", "public" ] },
|
||||
{ include: [ "<__tuple/find_index.h>", "private", "<tuple>", "public" ] },
|
||||
{ include: [ "<__tuple/make_tuple_types.h>", "private", "<tuple>", "public" ] },
|
||||
{ include: [ "<__tuple/pair_like.h>", "private", "<tuple>", "public" ] },
|
||||
{ include: [ "<__tuple/sfinae_helpers.h>", "private", "<tuple>", "public" ] },
|
||||
{ include: [ "<__tuple/tuple_element.h>", "private", "<tuple>", "public" ] },
|
||||
{ include: [ "<__tuple/tuple_indices.h>", "private", "<tuple>", "public" ] },
|
||||
{ include: [ "<__tuple/tuple_like.h>", "private", "<tuple>", "public" ] },
|
||||
{ include: [ "<__tuple/tuple_like_ext.h>", "private", "<tuple>", "public" ] },
|
||||
{ include: [ "<__tuple/tuple_like_no_subrange.h>", "private", "<tuple>", "public" ] },
|
||||
{ include: [ "<__tuple/tuple_size.h>", "private", "<tuple>", "public" ] },
|
||||
{ include: [ "<__tuple/tuple_types.h>", "private", "<tuple>", "public" ] },
|
||||
{ include: [ "<__type_traits/add_const.h>", "private", "<type_traits>", "public" ] },
|
||||
|
||||
@@ -1810,20 +1810,22 @@ module std_private_thread_thread [system] {
|
||||
}
|
||||
module std_private_thread_timed_backoff_policy [system] { header "__thread/timed_backoff_policy.h" }
|
||||
|
||||
module std_private_tuple_find_index [system] { header "__tuple/find_index.h" }
|
||||
module std_private_tuple_make_tuple_types [system] { header "__tuple/make_tuple_types.h" }
|
||||
module std_private_tuple_pair_like [system] {
|
||||
header "__tuple/pair_like.h"
|
||||
export std_private_tuple_tuple_like
|
||||
module std_private_tuple_find_index [system] { header "__tuple/find_index.h" }
|
||||
module std_private_tuple_make_tuple_types [system] { header "__tuple/make_tuple_types.h" }
|
||||
module std_private_tuple_tuple_like_no_subrange [system] {
|
||||
header "__tuple/tuple_like_no_subrange.h"
|
||||
}
|
||||
module std_private_tuple_sfinae_helpers [system] { header "__tuple/sfinae_helpers.h" }
|
||||
module std_private_tuple_tuple_element [system] { header "__tuple/tuple_element.h" }
|
||||
module std_private_tuple_tuple_fwd [system] { header "__fwd/tuple.h" }
|
||||
module std_private_tuple_tuple_indices [system] { header "__tuple/tuple_indices.h" }
|
||||
module std_private_tuple_tuple_like [system] { header "__tuple/tuple_like.h" }
|
||||
module std_private_tuple_tuple_like_ext [system] { header "__tuple/tuple_like_ext.h" }
|
||||
module std_private_tuple_tuple_size [system] { header "__tuple/tuple_size.h" }
|
||||
module std_private_tuple_tuple_types [system] { header "__tuple/tuple_types.h" }
|
||||
module std_private_tuple_sfinae_helpers [system] { header "__tuple/sfinae_helpers.h" }
|
||||
module std_private_tuple_tuple_element [system] { header "__tuple/tuple_element.h" }
|
||||
module std_private_tuple_tuple_fwd [system] { header "__fwd/tuple.h" }
|
||||
module std_private_tuple_tuple_indices [system] { header "__tuple/tuple_indices.h" }
|
||||
module std_private_tuple_tuple_like [system] {
|
||||
header "__tuple/tuple_like.h"
|
||||
export *
|
||||
}
|
||||
module std_private_tuple_tuple_like_ext [system] { header "__tuple/tuple_like_ext.h" }
|
||||
module std_private_tuple_tuple_size [system] { header "__tuple/tuple_size.h" }
|
||||
module std_private_tuple_tuple_types [system] { header "__tuple/tuple_types.h" }
|
||||
|
||||
module std_private_type_traits_add_const [system] { header "__type_traits/add_const.h" }
|
||||
module std_private_type_traits_add_cv [system] { header "__type_traits/add_cv.h" }
|
||||
|
||||
@@ -235,11 +235,13 @@ namespace std {
|
||||
#include <__type_traits/is_destructible.h>
|
||||
#include <__type_traits/is_nothrow_assignable.h>
|
||||
#include <__type_traits/is_nothrow_constructible.h>
|
||||
#include <__type_traits/is_reference.h>
|
||||
#include <__type_traits/is_trivially_assignable.h>
|
||||
#include <__type_traits/is_trivially_constructible.h>
|
||||
#include <__type_traits/is_trivially_destructible.h>
|
||||
#include <__type_traits/is_void.h>
|
||||
#include <__type_traits/remove_const.h>
|
||||
#include <__type_traits/remove_cvref.h>
|
||||
#include <__type_traits/type_identity.h>
|
||||
#include <__type_traits/void_t.h>
|
||||
#include <__utility/declval.h>
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
// template<class T>
|
||||
// concept tuple-like; // exposition only
|
||||
|
||||
#include <__tuple/tuple_like.h>
|
||||
#include <array>
|
||||
#include <complex>
|
||||
#include <ranges>
|
||||
|
||||
@@ -52,7 +52,6 @@ static_assert(!std::ranges::input_range<Range<cpp20_output_iterator<std::tuple<i
|
||||
static_assert(!HasElementsView<Range<cpp20_output_iterator<std::tuple<int>*>>, 0>);
|
||||
|
||||
// !tuple-like
|
||||
LIBCPP_STATIC_ASSERT(!std::__tuple_like<int>);
|
||||
static_assert(!HasElementsView<Range<int*>, 1>);
|
||||
|
||||
// !(N < tuple_size_v<T>)
|
||||
|
||||
Reference in New Issue
Block a user