CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
528 lines
19 KiB
C++
528 lines
19 KiB
C++
// RUN: %clang_cc1 -std=c++2c -fexperimental-new-constant-interpreter -verify=expected,both %s
|
|
// RUN: %clang_cc1 -std=c++2c -verify=ref,both %s
|
|
|
|
/// This used to cause an assertion failure because we were deallocating a
|
|
/// dynamic block that was already dead.
|
|
|
|
namespace std {
|
|
inline namespace __1 {
|
|
template <class _Tp, _Tp __v> struct integral_constant {
|
|
static inline constexpr const _Tp value = __v;
|
|
};
|
|
typedef integral_constant<bool, true> true_type;
|
|
typedef integral_constant<bool, false> false_type;
|
|
template <bool _Val> using _BoolConstant = integral_constant<bool, _Val>;
|
|
template <class _Tp> using __remove_cv_t = __remove_cv(_Tp);
|
|
template <class _Tp> using remove_cv_t = __remove_cv_t<_Tp>;
|
|
template <class _Tp>
|
|
inline constexpr bool is_lvalue_reference_v = __is_lvalue_reference(_Tp);
|
|
template <class _Tp>
|
|
using __libcpp_remove_reference_t = __remove_reference_t(_Tp);
|
|
template <class _Tp>
|
|
constexpr _Tp &&forward(__libcpp_remove_reference_t<_Tp> &__t) noexcept;
|
|
template <bool _Bp, class _If, class _Then> struct conditional {
|
|
using type = _If;
|
|
};
|
|
template <bool _Bp, class _IfRes, class _ElseRes>
|
|
using conditional_t = typename conditional<_Bp, _IfRes, _ElseRes>::type;
|
|
template <class _Tp, class _Up>
|
|
using _IsSame = _BoolConstant<__is_same(_Tp, _Up)>;
|
|
using size_t = decltype(sizeof(int));
|
|
template <class _Tp> using __decay_t = __decay(_Tp);
|
|
template <class _Tp> using decay_t = __decay_t<_Tp>;
|
|
template <bool, class _Tp = void> struct enable_if;
|
|
template <class _Tp> struct enable_if<true, _Tp> {
|
|
typedef _Tp type;
|
|
};
|
|
template <bool _Bp, class _Tp = void>
|
|
using __enable_if_t = typename enable_if<_Bp, _Tp>::type;
|
|
template <class _Bp, class _Dp>
|
|
inline constexpr bool is_base_of_v = __is_base_of(_Bp, _Dp);
|
|
template <class _Tp> _Tp &&__declval(int);
|
|
template <class _Tp> decltype(std::__declval<_Tp>(0)) declval() noexcept;
|
|
template <class _Ret, class _Fp, class... _Args> struct __invokable_r {};
|
|
template <class _Fp, class... _Args>
|
|
using __is_invocable = __invokable_r<void, _Fp, _Args...>;
|
|
template <class _Func, class... _Args>
|
|
inline const bool __is_invocable_v = __is_invocable<_Func, _Args...>::value;
|
|
template <class _Func, class... _Args>
|
|
struct __invoke_result
|
|
: enable_if<__is_invocable_v<_Func, _Args...>,
|
|
typename __invokable_r<void, _Func, _Args...>::_Result> {};
|
|
template <class _Fn, class... _Args>
|
|
struct invoke_result : __invoke_result<_Fn, _Args...> {};
|
|
template <class _Tp, class... _Args>
|
|
inline constexpr bool is_constructible_v = __is_constructible(_Tp, _Args...);
|
|
template <class _Tp>
|
|
constexpr __libcpp_remove_reference_t<_Tp> &&move(_Tp &&__t) noexcept;
|
|
template <class _Tp> inline constexpr bool is_enum_v = __is_enum(_Tp);
|
|
template <class _From, class _To>
|
|
inline constexpr bool is_convertible_v = __is_convertible(_From, _To);
|
|
template <class _From, class _To>
|
|
concept convertible_to = is_convertible_v<_From, _To> &&
|
|
requires { static_cast<_To>(std::declval<_From>()); };
|
|
template <class _Tp, class _Up>
|
|
concept __same_as_impl = _IsSame<_Tp, _Up>::value;
|
|
template <class _Tp, class _Up>
|
|
concept same_as = __same_as_impl<_Tp, _Up> && __same_as_impl<_Up, _Tp>;
|
|
template <class _Tp> using __remove_cvref_t = __remove_cvref(_Tp);
|
|
template <class _Tp> using remove_cvref_t = __remove_cvref_t<_Tp>;
|
|
template <class _Tp>
|
|
using __make_const_lvalue_ref = const __libcpp_remove_reference_t<_Tp> &;
|
|
template <class _Lhs, class _Rhs>
|
|
concept assignable_from =
|
|
is_lvalue_reference_v<_Lhs> &&
|
|
requires(_Lhs __lhs, _Rhs &&__rhs) {
|
|
{ __lhs = std::forward<_Rhs>(__rhs) } -> same_as<_Lhs>;
|
|
};
|
|
template <class _Tp>
|
|
struct is_nothrow_destructible
|
|
: integral_constant<bool, __is_nothrow_destructible(_Tp)> {};
|
|
template <class _Tp>
|
|
inline constexpr bool is_nothrow_destructible_v =
|
|
is_nothrow_destructible<_Tp>::value;
|
|
template <class _Tp>
|
|
concept destructible = is_nothrow_destructible_v<_Tp>;
|
|
template <class _Tp, class... _Args>
|
|
concept constructible_from =
|
|
destructible<_Tp> && is_constructible_v<_Tp, _Args...>;
|
|
template <class _Tp>
|
|
concept __default_initializable = requires { ::new _Tp; };
|
|
template <class _Tp>
|
|
concept default_initializable = constructible_from<_Tp> && requires {
|
|
_Tp{};
|
|
} && __default_initializable<_Tp>;
|
|
template <class _Tp>
|
|
concept move_constructible =
|
|
constructible_from<_Tp, _Tp> && convertible_to<_Tp, _Tp>;
|
|
template <class _Tp> inline constexpr bool is_class_v = __is_class(_Tp);
|
|
template <class _Tp> inline constexpr bool is_union_v = __is_union(_Tp);
|
|
template <class _Tp>
|
|
concept __class_or_enum = is_class_v<_Tp> || is_union_v<_Tp> || is_enum_v<_Tp>;
|
|
namespace ranges {
|
|
namespace __swap {
|
|
template <class _Tp, class _Up>
|
|
concept __unqualified_swappable_with =
|
|
(__class_or_enum<remove_cvref_t<_Tp>> ||
|
|
__class_or_enum<remove_cvref_t<_Up>>) &&
|
|
requires(_Tp &&__t, _Up &&__u) {
|
|
swap(std::forward<_Tp>(__t), std::forward<_Up>(__u));
|
|
};
|
|
template <class _Tp>
|
|
concept __exchangeable = !__unqualified_swappable_with<_Tp &, _Tp &> &&
|
|
move_constructible<_Tp> && assignable_from<_Tp &, _Tp>;
|
|
struct __fn {
|
|
template <__exchangeable _Tp>
|
|
constexpr void operator()(_Tp &__x, _Tp &__y) const;
|
|
};
|
|
} // namespace __swap
|
|
inline namespace __cpo {
|
|
inline constexpr auto swap = __swap::__fn{};
|
|
}
|
|
} // namespace ranges
|
|
template <class _Tp> inline constexpr bool is_object_v = __is_object(_Tp);
|
|
template <class _Tp>
|
|
concept movable = is_object_v<_Tp> && move_constructible<_Tp> &&
|
|
assignable_from<_Tp &, _Tp>;
|
|
template <class _Tp>
|
|
concept copyable =
|
|
assignable_from<_Tp &, const _Tp &> && assignable_from<_Tp &, const _Tp>;
|
|
template <class _Dp, class _Bp>
|
|
concept derived_from =
|
|
is_base_of_v<_Bp, _Dp> &&
|
|
is_convertible_v<const volatile _Dp *, const volatile _Bp *>;
|
|
template <class _Tp>
|
|
concept __boolean_testable_impl = convertible_to<_Tp, bool>;
|
|
template <class _Tp>
|
|
concept __boolean_testable =
|
|
__boolean_testable_impl<_Tp> && requires(_Tp &&__t) {
|
|
{ !std::forward<_Tp>(__t) } -> __boolean_testable_impl;
|
|
};
|
|
template <class _Tp, class _Up>
|
|
concept __weakly_equality_comparable_with = requires(
|
|
__make_const_lvalue_ref<_Tp> __t, __make_const_lvalue_ref<_Up> __u) {
|
|
{ __u != __t } -> __boolean_testable;
|
|
};
|
|
template <class _Tp>
|
|
concept semiregular = copyable<_Tp> && default_initializable<_Tp>;
|
|
template <template <class...> class _Templ, class... _Args,
|
|
class = _Templ<_Args...>>
|
|
true_type __sfinae_test_impl(int);
|
|
template <template <class...> class, class...>
|
|
false_type __sfinae_test_impl(...);
|
|
template <template <class...> class _Templ, class... _Args>
|
|
using _IsValidExpansion =
|
|
decltype(std::__sfinae_test_impl<_Templ, _Args...>(0));
|
|
template <class _Tp>
|
|
using __test_for_primary_template =
|
|
__enable_if_t<_IsSame<_Tp, typename _Tp::__primary_template>::value>;
|
|
template <class _Tp>
|
|
using __is_primary_template =
|
|
_IsValidExpansion<__test_for_primary_template, _Tp>;
|
|
template <class> struct iterator_traits;
|
|
template <class> struct __cond_value_type;
|
|
template <class _Tp>
|
|
requires is_object_v<_Tp>
|
|
struct __cond_value_type<_Tp> {
|
|
using value_type = remove_cv_t<_Tp>;
|
|
};
|
|
template <class _Tp>
|
|
concept __has_member_value_type = requires { typename _Tp::value_type; };
|
|
template <class> struct indirectly_readable_traits;
|
|
template <class _Tp>
|
|
struct indirectly_readable_traits<_Tp *> : __cond_value_type<_Tp> {};
|
|
template <__has_member_value_type _Tp>
|
|
struct indirectly_readable_traits<_Tp>
|
|
: __cond_value_type<typename _Tp::value_type> {};
|
|
template <bool> struct _OrImpl;
|
|
template <> struct _OrImpl<true> {
|
|
template <class _Res, class _First, class... _Rest>
|
|
using _Result =
|
|
typename _OrImpl<!bool(_First::value) && sizeof...(_Rest) != 0>::
|
|
template _Result<_First, _Rest...>;
|
|
};
|
|
template <> struct _OrImpl<false> {
|
|
template <class _Res, class...> using _Result = _Res;
|
|
};
|
|
template <class... _Args>
|
|
using _Or = typename _OrImpl<sizeof...(_Args) !=
|
|
0>::template _Result<false_type, _Args...>;
|
|
template <class _Tp> using __with_reference = _Tp &;
|
|
template <class _Tp>
|
|
concept __can_reference = requires { typename __with_reference<_Tp>; };
|
|
template <class _Tp>
|
|
concept __dereferenceable = requires(_Tp &__t) {
|
|
{ *__t } -> __can_reference;
|
|
};
|
|
template <__dereferenceable _Tp>
|
|
using iter_reference_t = decltype(*std::declval<_Tp &>());
|
|
struct input_iterator_tag {};
|
|
struct forward_iterator_tag : public input_iterator_tag {};
|
|
struct bidirectional_iterator_tag : public forward_iterator_tag {};
|
|
struct random_access_iterator_tag : public bidirectional_iterator_tag {};
|
|
template <class _Iter> struct __iter_traits_cache;
|
|
template <class _Iter>
|
|
using _ITER_TRAITS = typename __iter_traits_cache<_Iter>::type;
|
|
struct __iter_concept_concept_test {
|
|
template <class _Iter>
|
|
using _Apply = typename _ITER_TRAITS<_Iter>::iterator_concept;
|
|
};
|
|
struct __iter_concept_category_test {
|
|
template <class _Iter>
|
|
using _Apply = typename _ITER_TRAITS<_Iter>::iterator_category;
|
|
};
|
|
struct __iter_concept_random_fallback {
|
|
template <class _Iter>
|
|
using _Apply =
|
|
__enable_if_t<__is_primary_template<iterator_traits<_Iter>>::value,
|
|
random_access_iterator_tag>;
|
|
};
|
|
template <class _Iter, class _Tester>
|
|
struct __test_iter_concept : _IsValidExpansion<_Tester::template _Apply, _Iter>,
|
|
_Tester {};
|
|
template <class _Iter> struct __iter_concept_cache {
|
|
using type = _Or<__test_iter_concept<_Iter, __iter_concept_concept_test>,
|
|
__test_iter_concept<_Iter, __iter_concept_category_test>,
|
|
__test_iter_concept<_Iter, __iter_concept_random_fallback>>;
|
|
};
|
|
template <class _Iter>
|
|
using _ITER_CONCEPT =
|
|
typename __iter_concept_cache<_Iter>::type::template _Apply<_Iter>;
|
|
template <class _Ip> struct iterator_traits {
|
|
using __primary_template = iterator_traits;
|
|
};
|
|
template <class _Ip>
|
|
using iter_value_t = typename conditional_t<
|
|
__is_primary_template<iterator_traits<remove_cvref_t<_Ip>>>::value,
|
|
indirectly_readable_traits<remove_cvref_t<_Ip>>,
|
|
iterator_traits<remove_cvref_t<_Ip>>>::value_type;
|
|
namespace ranges {
|
|
namespace __iter_move {
|
|
template <class _Tp>
|
|
concept __move_deref = requires(_Tp &&__t) {
|
|
requires is_lvalue_reference_v<decltype(*__t)>;
|
|
};
|
|
struct __fn {
|
|
template <class _Ip>
|
|
requires __move_deref<_Ip>
|
|
constexpr auto operator()(_Ip &&__i) const
|
|
-> decltype(std::move(*std::forward<_Ip>(__i))) {
|
|
return std::move(*std::forward<_Ip>(__i));
|
|
}
|
|
template <class _Ip>
|
|
constexpr auto operator()(_Ip &&__i) const
|
|
-> decltype(*std::forward<_Ip>(__i));
|
|
};
|
|
} // namespace __iter_move
|
|
inline namespace __cpo {
|
|
inline constexpr auto iter_move = __iter_move::__fn{};
|
|
}
|
|
} // namespace ranges
|
|
template <__dereferenceable _Tp>
|
|
requires requires(_Tp &__t) {
|
|
{ ranges::iter_move(__t) } -> __can_reference;
|
|
}
|
|
using iter_rvalue_reference_t =
|
|
decltype(ranges::iter_move(std::declval<_Tp &>()));
|
|
template <class _Ptr, class = void> struct __pointer_traits_impl {};
|
|
template <class _Tp> inline constexpr bool is_pointer_v = __is_pointer(_Tp);
|
|
template <class _Ip>
|
|
concept input_or_output_iterator = requires(_Ip __i) {
|
|
{ *__i } -> __can_reference;
|
|
};
|
|
template <class _Sp, class _Ip>
|
|
concept sentinel_for = semiregular<_Sp> && input_or_output_iterator<_Ip> &&
|
|
__weakly_equality_comparable_with<_Sp, _Ip>;
|
|
template <class _Ip>
|
|
concept input_iterator =
|
|
input_or_output_iterator<_Ip> && requires {
|
|
typename _ITER_CONCEPT<_Ip>;
|
|
} && derived_from<_ITER_CONCEPT<_Ip>, input_iterator_tag>;
|
|
namespace ranges {
|
|
namespace __begin {
|
|
struct __fn {
|
|
template <class _Tp> constexpr auto operator()(_Tp &&__t) const {
|
|
return static_cast<::std::__decay_t<decltype((__t.begin()))>>(__t.begin());
|
|
}
|
|
};
|
|
} // namespace __begin
|
|
inline namespace __cpo {
|
|
inline constexpr auto begin = __begin::__fn{};
|
|
}
|
|
template <class _Tp>
|
|
using iterator_t = decltype(ranges::begin(std::declval<_Tp &>()));
|
|
namespace __end {
|
|
struct __fn {
|
|
template <class _Tp> constexpr auto operator()(_Tp &&__t) const {}
|
|
};
|
|
} // namespace __end
|
|
inline namespace __cpo {
|
|
inline constexpr auto end = __end::__fn{};
|
|
}
|
|
} // namespace ranges
|
|
namespace ranges {
|
|
template <class _Tp>
|
|
concept range = requires(_Tp &__t) { ranges::end(__t); };
|
|
template <class _Tp>
|
|
concept input_range = range<_Tp> && input_iterator<iterator_t<_Tp>>;
|
|
template <range _Rp> using range_value_t = iter_value_t<iterator_t<_Rp>>;
|
|
} // namespace ranges
|
|
} // namespace __1
|
|
} // namespace std
|
|
constexpr void *operator new(std::size_t, void *__p) noexcept; // both-warning {{not defined}}
|
|
namespace std {
|
|
inline namespace __1 {
|
|
template <class _Tp, class... _Args,
|
|
class = decltype(::new (std::declval<void *>())
|
|
_Tp(std::declval<_Args>()...))>
|
|
constexpr _Tp *construct_at(_Tp *__location, _Args &&...__args) {
|
|
return ::new (static_cast<void *>(__location)) _Tp(std::forward<_Args>(__args)...); // both-note {{here}}
|
|
}
|
|
enum class __element_count : size_t;
|
|
template <class _Tp, class _Up>
|
|
constexpr _Tp *__constexpr_memmove(_Tp *__dest, _Up *__src,
|
|
__element_count __n) {
|
|
size_t __count = static_cast<size_t>(__n);
|
|
::__builtin_memcpy(__dest, __src, __count * sizeof(_Tp));
|
|
return __dest;
|
|
};
|
|
namespace ranges {
|
|
template <class _From, class _To>
|
|
concept __convertible_to_non_slicing =
|
|
convertible_to<_From, _To>;
|
|
template <input_or_output_iterator _Iter, sentinel_for<_Iter> _Sent = _Iter>
|
|
class subrange {
|
|
private:
|
|
_Iter __begin_ = _Iter();
|
|
_Sent __end_ = _Sent();
|
|
|
|
public:
|
|
constexpr subrange(__convertible_to_non_slicing<_Iter> auto __iter,
|
|
_Sent __sent)
|
|
: __begin_(std::move(__iter)), __end_(std::move(__sent)) {}
|
|
constexpr _Iter begin() { return std::move(__begin_); }
|
|
constexpr _Sent end() const;
|
|
};
|
|
template <input_or_output_iterator _Iter, sentinel_for<_Iter> _Sent>
|
|
subrange(_Iter, _Sent) -> subrange<_Iter, _Sent>;
|
|
} // namespace ranges
|
|
template <class _Tp> class allocator {
|
|
public:
|
|
constexpr _Tp *allocate(size_t __n) {
|
|
return static_cast<_Tp *>(::operator new(__n * sizeof(_Tp)));
|
|
}
|
|
constexpr void deallocate(_Tp *__p, size_t __n) noexcept {
|
|
::operator delete(__p);
|
|
}
|
|
};
|
|
template <class _CharT> struct char_traits;
|
|
template <class _CharT, class _Traits = char_traits<_CharT>,
|
|
class _Allocator = allocator<_CharT>>
|
|
class basic_string;
|
|
using string = basic_string<char>;
|
|
template <class _Iter>
|
|
class move_iterator {
|
|
private:
|
|
public:
|
|
using iterator_type = _Iter;
|
|
using value_type = iter_value_t<_Iter>;
|
|
using reference = iter_rvalue_reference_t<_Iter>;
|
|
constexpr explicit move_iterator(_Iter __i) : __current_(std::move(__i)) {}
|
|
constexpr move_iterator();
|
|
constexpr reference operator*() const {
|
|
return ranges::iter_move(__current_);
|
|
}
|
|
_Iter __current_;
|
|
};
|
|
namespace ranges {
|
|
template <class _T1> struct min_max_result {
|
|
_T1 min;
|
|
};
|
|
template <class _T1> using minmax_result = min_max_result<_T1>;
|
|
struct __minmax {
|
|
template <input_range _Range>
|
|
constexpr ranges::minmax_result<range_value_t<_Range>>
|
|
operator()(_Range &&__r) const {
|
|
auto __first = ranges::begin(__r);
|
|
using _ValueT = range_value_t<_Range>;
|
|
ranges::minmax_result<_ValueT> __result = {*__first};
|
|
return __result;
|
|
}
|
|
};
|
|
inline namespace __cpo {
|
|
inline constexpr auto minmax = __minmax{};
|
|
}
|
|
} // namespace ranges
|
|
template <> struct char_traits<char> {
|
|
using char_type = char;
|
|
static constexpr int compare(const char_type *__lhs, const char_type *__rhs,
|
|
size_t __count) noexcept {
|
|
return __builtin_memcmp(__lhs, __rhs, __count);
|
|
}
|
|
static inline size_t constexpr length(const char_type *__s) noexcept {
|
|
return __builtin_strlen(__s);
|
|
}
|
|
static inline constexpr char_type *
|
|
copy(char_type *__s1, const char_type *__s2, size_t __n) noexcept {
|
|
std::__constexpr_memmove(__s1, __s2, __element_count(__n));
|
|
return __s1;
|
|
}
|
|
};
|
|
template <class _CharT, class _Traits, class _Allocator> class basic_string {
|
|
using traits_type = _Traits;
|
|
using value_type = _CharT;
|
|
using allocator_type = _Allocator;
|
|
|
|
private:
|
|
struct __long {
|
|
struct {
|
|
unsigned __is_long_ : 1;
|
|
unsigned __cap_ : sizeof(unsigned) * 8 - 1;
|
|
};
|
|
unsigned __size_;
|
|
char *__data_;
|
|
};
|
|
struct __short {
|
|
struct {
|
|
unsigned char __is_long_ : 1;
|
|
};
|
|
};
|
|
union __rep {
|
|
__short __s;
|
|
__long __l;
|
|
};
|
|
__rep __rep_;
|
|
allocator_type __alloc_;
|
|
|
|
public:
|
|
constexpr basic_string(const basic_string &__str) : __alloc_(__str.__alloc_) {
|
|
__init_copy_ctor_external(__str.__rep_.__l.__data_,
|
|
__str.__rep_.__l.__size_);
|
|
}
|
|
constexpr basic_string(basic_string &&__str)
|
|
: __rep_(__str.__rep_), __alloc_(std::move(__str.__alloc_)) {
|
|
__str.__rep_ = __rep();
|
|
}
|
|
constexpr basic_string(const _CharT *__s) {
|
|
__init_copy_ctor_external(__s, traits_type::length(__s));
|
|
}
|
|
inline constexpr ~basic_string() {
|
|
if (__is_long())
|
|
__alloc_.deallocate(__rep_.__l.__data_, __rep_.__l.__cap_*2);
|
|
}
|
|
constexpr unsigned size() const noexcept { return __rep_.__l.__size_; }
|
|
constexpr const value_type *data() const noexcept { return __rep_.__l.__data_; }
|
|
|
|
private:
|
|
constexpr bool __is_long() const {
|
|
if (__builtin_constant_p(__rep_.__l.__is_long_)) {
|
|
return __rep_.__l.__is_long_;
|
|
}
|
|
return __rep_.__s.__is_long_;
|
|
}
|
|
static constexpr void __begin_lifetime(char *__begin, unsigned __n) {
|
|
for (unsigned __i = 0; __i != __n; ++__i)
|
|
std::construct_at(&__begin[__i]);
|
|
}
|
|
constexpr void __init_copy_ctor_external(const value_type *__s,
|
|
unsigned __sz);
|
|
};
|
|
template <class _CharT, class _Traits, class _Allocator>
|
|
constexpr void
|
|
basic_string<_CharT, _Traits, _Allocator>::__init_copy_ctor_external(
|
|
const value_type *__s, unsigned __sz) {
|
|
char *__p;
|
|
auto __allocation = __alloc_.allocate(__sz + 1);
|
|
__p = __allocation;
|
|
__begin_lifetime(__p, __sz + 1);
|
|
__rep_.__l.__data_ = __p;
|
|
__rep_.__l.__cap_ = (__sz + 1) / 2;
|
|
__rep_.__l.__is_long_ = true;
|
|
__rep_.__l.__size_ = __sz;
|
|
traits_type::copy(__p, __s, __sz + 1);
|
|
}
|
|
template <class _CharT, class _Traits, class _Allocator>
|
|
inline constexpr bool
|
|
operator==(const basic_string<_CharT, _Traits, _Allocator> &__lhs,
|
|
const basic_string<_CharT, _Traits, _Allocator> &__rhs) noexcept {
|
|
return _Traits::compare(__lhs.data(), __rhs.data(), __lhs.size()) == 0;
|
|
}
|
|
} // namespace __1
|
|
} // namespace std
|
|
template <class It> class cpp20_input_iterator {
|
|
It it_;
|
|
|
|
public:
|
|
using value_type = std::iter_value_t<It>;
|
|
constexpr explicit cpp20_input_iterator(It it) : it_(it) {}
|
|
constexpr decltype(auto) operator*() const { return *it_; }
|
|
constexpr void operator++(int);
|
|
friend constexpr It base(const cpp20_input_iterator &i) { return i.it_; }
|
|
};
|
|
template <class It> class sentinel_wrapper {
|
|
public:
|
|
explicit sentinel_wrapper() = default;
|
|
constexpr explicit sentinel_wrapper(const It &it) : base_(base(it)) {}
|
|
constexpr bool operator==(const It &other) const;
|
|
|
|
private:
|
|
decltype(base(std::declval<It>())) base_;
|
|
};
|
|
constexpr bool test_range() {
|
|
const std::string str{
|
|
"this long string will be dynamically "
|
|
"allocatedasfajkshdfasdhjkfahjksdgfjkasdhkfgaksdgfhkasghjkdfgjhasdghjfgah"
|
|
"jksdgjfhkasghjkdfghjasgjdfghasdghjkfgajksdgfgajsdfghjkgashjkdfghjasjdhkf"
|
|
"gahjsdfghjkgashjdghjfkasghjkdfasgjkdhfgajkshdfgkjashdgfkjasghdfkjghasdkf"
|
|
"hgaskdjghfasdfasdfasdfasdfasdf"};
|
|
std::string a[] = {str};
|
|
auto range = std::ranges::subrange(
|
|
cpp20_input_iterator(std::move_iterator(a)),
|
|
sentinel_wrapper(cpp20_input_iterator(std::move_iterator(a + 1))));
|
|
auto ret = std::ranges::minmax(range);
|
|
if (ret.min != str)
|
|
__builtin_abort();
|
|
return true;
|
|
}
|
|
static_assert(test_range());
|