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_STRING_VIEW
11#define _LIBCPP_STRING_VIEW
12
13// clang-format off
14
15/*
16
17 string_view synopsis
18
19#include <compare>
20
21namespace std {
22
23 // 7.2, Class template basic_string_view
24 template<class charT, class traits = char_traits<charT>>
25 class basic_string_view;
26
27 template<class charT, class traits>
28 inline constexpr bool ranges::enable_view<basic_string_view<charT, traits>> = true;
29
30 template<class charT, class traits>
31 inline constexpr bool ranges::enable_borrowed_range<basic_string_view<charT, traits>> = true; // C++20
32
33 // 7.9, basic_string_view non-member comparison functions
34 template<class charT, class traits>
35 constexpr bool operator==(basic_string_view<charT, traits> x,
36 basic_string_view<charT, traits> y) noexcept;
37 template<class charT, class traits> // Removed in C++20
38 constexpr bool operator!=(basic_string_view<charT, traits> x,
39 basic_string_view<charT, traits> y) noexcept;
40 template<class charT, class traits> // Removed in C++20
41 constexpr bool operator< (basic_string_view<charT, traits> x,
42 basic_string_view<charT, traits> y) noexcept;
43 template<class charT, class traits> // Removed in C++20
44 constexpr bool operator> (basic_string_view<charT, traits> x,
45 basic_string_view<charT, traits> y) noexcept;
46 template<class charT, class traits> // Removed in C++20
47 constexpr bool operator<=(basic_string_view<charT, traits> x,
48 basic_string_view<charT, traits> y) noexcept;
49 template<class charT, class traits> // Removed in C++20
50 constexpr bool operator>=(basic_string_view<charT, traits> x,
51 basic_string_view<charT, traits> y) noexcept;
52 template<class charT, class traits> // Since C++20
53 constexpr see below operator<=>(basic_string_view<charT, traits> x,
54 basic_string_view<charT, traits> y) noexcept;
55
56 // see below, sufficient additional overloads of comparison functions
57
58 // 7.10, Inserters and extractors
59 template<class charT, class traits>
60 basic_ostream<charT, traits>&
61 operator<<(basic_ostream<charT, traits>& os,
62 basic_string_view<charT, traits> str);
63
64 // basic_string_view typedef names
65 typedef basic_string_view<char> string_view;
66 typedef basic_string_view<char8_t> u8string_view; // C++20
67 typedef basic_string_view<char16_t> u16string_view;
68 typedef basic_string_view<char32_t> u32string_view;
69 typedef basic_string_view<wchar_t> wstring_view;
70
71 template<class charT, class traits = char_traits<charT>>
72 class basic_string_view {
73 public:
74 // types
75 typedef traits traits_type;
76 typedef charT value_type;
77 typedef charT* pointer;
78 typedef const charT* const_pointer;
79 typedef charT& reference;
80 typedef const charT& const_reference;
81 typedef implementation-defined const_iterator;
82 typedef const_iterator iterator;
83 typedef reverse_iterator<const_iterator> const_reverse_iterator;
84 typedef const_reverse_iterator reverse_iterator;
85 typedef size_t size_type;
86 typedef ptrdiff_t difference_type;
87 static constexpr size_type npos = size_type(-1);
88
89 // 7.3, basic_string_view constructors and assignment operators
90 constexpr basic_string_view() noexcept;
91 constexpr basic_string_view(const basic_string_view&) noexcept = default;
92 basic_string_view& operator=(const basic_string_view&) noexcept = default;
93 template<class Allocator>
94 constexpr basic_string_view(const charT* str);
95 basic_string_view(nullptr_t) = delete; // C++23
96 constexpr basic_string_view(const charT* str, size_type len);
97 template <class It, class End>
98 constexpr basic_string_view(It begin, End end); // C++20
99 template <class Range>
100 constexpr basic_string_view(Range&& r); // C++23
101
102 // 7.4, basic_string_view iterator support
103 constexpr const_iterator begin() const noexcept;
104 constexpr const_iterator end() const noexcept;
105 constexpr const_iterator cbegin() const noexcept;
106 constexpr const_iterator cend() const noexcept;
107 const_reverse_iterator rbegin() const noexcept;
108 const_reverse_iterator rend() const noexcept;
109 const_reverse_iterator crbegin() const noexcept;
110 const_reverse_iterator crend() const noexcept;
111
112 // 7.5, basic_string_view capacity
113 constexpr size_type size() const noexcept;
114 constexpr size_type length() const noexcept;
115 constexpr size_type max_size() const noexcept;
116 constexpr bool empty() const noexcept;
117
118 // 7.6, basic_string_view element access
119 constexpr const_reference operator[](size_type pos) const;
120 constexpr const_reference at(size_type pos) const;
121 constexpr const_reference front() const;
122 constexpr const_reference back() const;
123 constexpr const_pointer data() const noexcept;
124
125 // 7.7, basic_string_view modifiers
126 constexpr void remove_prefix(size_type n);
127 constexpr void remove_suffix(size_type n);
128 constexpr void swap(basic_string_view& s) noexcept;
129
130 size_type copy(charT* s, size_type n, size_type pos = 0) const; // constexpr in C++20
131
132 constexpr basic_string_view substr(size_type pos = 0, size_type n = npos) const;
133 constexpr basic_string_view subview(size_type pos = 0,
134 size_type n = npos) const; // freestanding-deleted, since C++26
135 constexpr int compare(basic_string_view s) const noexcept;
136 constexpr int compare(size_type pos1, size_type n1, basic_string_view s) const;
137 constexpr int compare(size_type pos1, size_type n1,
138 basic_string_view s, size_type pos2, size_type n2) const;
139 constexpr int compare(const charT* s) const;
140 constexpr int compare(size_type pos1, size_type n1, const charT* s) const;
141 constexpr int compare(size_type pos1, size_type n1,
142 const charT* s, size_type n2) const;
143 constexpr size_type find(basic_string_view s, size_type pos = 0) const noexcept;
144 constexpr size_type find(charT c, size_type pos = 0) const noexcept;
145 constexpr size_type find(const charT* s, size_type pos, size_type n) const noexcept; // noexcept as an extension
146 constexpr size_type find(const charT* s, size_type pos = 0) const noexcept; // noexcept as an extension
147 constexpr size_type rfind(basic_string_view s, size_type pos = npos) const noexcept;
148 constexpr size_type rfind(charT c, size_type pos = npos) const noexcept;
149 constexpr size_type rfind(const charT* s, size_type pos, size_type n) const noexcept; // noexcept as an extension
150 constexpr size_type rfind(const charT* s, size_type pos = npos) const noexcept; // noexcept as an extension
151 constexpr size_type find_first_of(basic_string_view s, size_type pos = 0) const noexcept;
152 constexpr size_type find_first_of(charT c, size_type pos = 0) const noexcept;
153 constexpr size_type find_first_of(const charT* s, size_type pos, size_type n) const noexcept; // noexcept as an extension
154 constexpr size_type find_first_of(const charT* s, size_type pos = 0) const noexcept; // noexcept as an extension
155 constexpr size_type find_last_of(basic_string_view s, size_type pos = npos) const noexcept;
156 constexpr size_type find_last_of(charT c, size_type pos = npos) const noexcept;
157 constexpr size_type find_last_of(const charT* s, size_type pos, size_type n) const noexcept; // noexcept as an extension
158 constexpr size_type find_last_of(const charT* s, size_type pos = npos) const noexcept; // noexcept as an extension
159 constexpr size_type find_first_not_of(basic_string_view s, size_type pos = 0) const noexcept;
160 constexpr size_type find_first_not_of(charT c, size_type pos = 0) const noexcept;
161 constexpr size_type find_first_not_of(const charT* s, size_type pos, size_type n) const noexcept; // noexcept as an extension
162 constexpr size_type find_first_not_of(const charT* s, size_type pos = 0) const noexcept; // noexcept as an extension
163 constexpr size_type find_last_not_of(basic_string_view s, size_type pos = npos) const noexcept;
164 constexpr size_type find_last_not_of(charT c, size_type pos = npos) const noexcept;
165 constexpr size_type find_last_not_of(const charT* s, size_type pos, size_type n) const noexcept; // noexcept as an extension
166 constexpr size_type find_last_not_of(const charT* s, size_type pos = npos) const noexcept; // noexcept as an extension
167
168 constexpr bool starts_with(basic_string_view s) const noexcept; // C++20
169 constexpr bool starts_with(charT c) const noexcept; // C++20
170 constexpr bool starts_with(const charT* s) const; // C++20
171 constexpr bool ends_with(basic_string_view s) const noexcept; // C++20
172 constexpr bool ends_with(charT c) const noexcept; // C++20
173 constexpr bool ends_with(const charT* s) const; // C++20
174
175 constexpr bool contains(basic_string_view s) const noexcept; // C++23
176 constexpr bool contains(charT c) const noexcept; // C++23
177 constexpr bool contains(const charT* s) const; // C++23
178
179 private:
180 const_pointer data_; // exposition only
181 size_type size_; // exposition only
182 };
183
184 // basic_string_view deduction guides
185 template<class It, class End>
186 basic_string_view(It, End) -> basic_string_view<iter_value_t<It>>; // C++20
187 template<class Range>
188 basic_string_view(Range&&) -> basic_string_view<ranges::range_value_t<Range>>; // C++23
189
190 // 7.11, Hash support
191 template <class T> struct hash;
192 template <> struct hash<string_view>;
193 template <> struct hash<u8string_view>; // C++20
194 template <> struct hash<u16string_view>;
195 template <> struct hash<u32string_view>;
196 template <> struct hash<wstring_view>;
197
198 constexpr basic_string_view<char> operator""sv(const char *str, size_t len) noexcept;
199 constexpr basic_string_view<wchar_t> operator""sv(const wchar_t *str, size_t len) noexcept;
200 constexpr basic_string_view<char8_t> operator""sv(const char8_t *str, size_t len) noexcept; // C++20
201 constexpr basic_string_view<char16_t> operator""sv(const char16_t *str, size_t len) noexcept;
202 constexpr basic_string_view<char32_t> operator""sv(const char32_t *str, size_t len) noexcept;
203
204} // namespace std
205
206*/
207
208// clang-format on
209
210#if __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)
211# include <__cxx03/string_view>
212#else
213# include <__algorithm/min.h>
214# include <__assert>
215# include <__config>
216# include <__cstddef/nullptr_t.h>
217# include <__cstddef/ptrdiff_t.h>
218# include <__cstddef/size_t.h>
219# include <__functional/hash.h>
220# include <__functional/unary_function.h>
221# include <__fwd/ostream.h>
222# include <__fwd/string.h>
223# include <__fwd/string_view.h>
224# include <__iterator/bounded_iter.h>
225# include <__iterator/concepts.h>
226# include <__iterator/iterator_traits.h>
227# include <__iterator/reverse_iterator.h>
228# include <__iterator/wrap_iter.h>
229# include <__memory/pointer_traits.h>
230# include <__ranges/concepts.h>
231# include <__ranges/data.h>
232# include <__ranges/enable_borrowed_range.h>
233# include <__ranges/enable_view.h>
234# include <__ranges/size.h>
235# include <__string/char_traits.h>
236# include <__type_traits/is_array.h>
237# include <__type_traits/is_convertible.h>
238# include <__type_traits/is_same.h>
239# include <__type_traits/is_standard_layout.h>
240# include <__type_traits/is_trivially_constructible.h>
241# include <__type_traits/is_trivially_copyable.h>
242# include <__type_traits/remove_cvref.h>
243# include <__type_traits/remove_reference.h>
244# include <__type_traits/type_identity.h>
245# include <iosfwd>
246# include <limits>
247# include <stdexcept>
248# include <version>
249
250// standard-mandated includes
251
252// [iterator.range]
253# include <__iterator/access.h>
254# include <__iterator/data.h>
255# include <__iterator/empty.h>
256# include <__iterator/reverse_access.h>
257# include <__iterator/size.h>
258
259// [string.view.synop]
260# include <compare>
261
262# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
263# pragma GCC system_header
264# endif
265
266_LIBCPP_PUSH_MACROS
267# include <__undef_macros>
268
269_LIBCPP_BEGIN_NAMESPACE_STD
270
271// TODO: This is a workaround for some vendors to carry a downstream diff to accept `nullptr` in
272// string_view constructors. This can be refactored when this exact form isn't needed anymore.
273template <class _Traits>
274_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR inline size_t
275__char_traits_length_checked(const typename _Traits::char_type* __s) _NOEXCEPT {
276 // This needs to be a single statement for C++11 constexpr
277 return _LIBCPP_ASSERT_NON_NULL(
278 __s != nullptr, "null pointer passed to non-null argument of char_traits<...>::length"),
279 _Traits::length(__s);
280}
281
282template <class _CharT, class _Traits>
283class basic_string_view {
284public:
285 // types
286 using traits_type = _Traits;
287 using value_type = _CharT;
288 using pointer = _CharT*;
289 using const_pointer = const _CharT*;
290 using reference = _CharT&;
291 using const_reference = const _CharT&;
292# if defined(_LIBCPP_ABI_BOUNDED_ITERATORS)
293 using const_iterator = __bounded_iter<const_pointer>;
294# elif defined(_LIBCPP_ABI_USE_WRAP_ITER_IN_STD_STRING_VIEW)
295 using const_iterator = __wrap_iter<const_pointer>;
296# else
297 using const_iterator = const_pointer;
298# endif
299 using iterator = const_iterator;
300 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
301 using reverse_iterator = const_reverse_iterator;
302 using size_type = size_t;
303 using difference_type = ptrdiff_t;
304 static _LIBCPP_CONSTEXPR const size_type npos = -1; // size_type(-1);
305
306 static_assert(!is_array<value_type>::value, "Character type of basic_string_view must not be an array");
307 static_assert(is_standard_layout<value_type>::value, "Character type of basic_string_view must be standard-layout");
308 static_assert(is_trivially_default_constructible<value_type>::value,
309 "Character type of basic_string_view must be trivially default constructible");
310 static_assert(is_trivially_copyable<value_type>::value,
311 "Character type of basic_string_view must be trivially copyable");
312 static_assert(is_same<_CharT, typename traits_type::char_type>::value,
313 "traits_type::char_type must be the same type as CharT");
314
315 // [string.view.cons], construct/copy
316 _LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI basic_string_view() _NOEXCEPT : __data_(nullptr), __size_(0) {}
317
318 _LIBCPP_HIDE_FROM_ABI basic_string_view(const basic_string_view&) _NOEXCEPT = default;
319
320 _LIBCPP_HIDE_FROM_ABI basic_string_view& operator=(const basic_string_view&) _NOEXCEPT = default;
321
322 _LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI basic_string_view(const _CharT* __s, size_type __len) _NOEXCEPT
323 _LIBCPP_DIAGNOSE_NULLPTR_IF(__len != 0 && __s == nullptr, " if len is not zero")
324 : __data_(__s), __size_(__len) {
325# if !defined(_LIBCPP_CXX03_LANG) && (!defined(_LIBCPP_COMPILER_GCC) || _LIBCPP_STD_VER >= 14)
326 // Allocations must fit in `ptrdiff_t` for pointer arithmetic to work. If `__len` exceeds it, the input
327 // range could not have been valid. Most likely the caller underflowed some arithmetic and inadvertently
328 // passed in a negative length.
329 _LIBCPP_ASSERT_VALID_INPUT_RANGE(
330 __len <= static_cast<size_type>(numeric_limits<difference_type>::max()),
331 "string_view::string_view(_CharT *, size_t): length does not fit in difference_type");
332 _LIBCPP_ASSERT_NON_NULL(
333 __len == 0 || __s != nullptr, "string_view::string_view(_CharT *, size_t): received nullptr");
334# endif
335 }
336
337# if _LIBCPP_STD_VER >= 20
338 template <contiguous_iterator _It, sized_sentinel_for<_It> _End>
339 requires(is_same_v<iter_value_t<_It>, _CharT> && !is_convertible_v<_End, size_type>)
340 constexpr _LIBCPP_HIDE_FROM_ABI basic_string_view(_It __begin, _End __end)
341 : __data_(std::to_address(__begin)), __size_(__end - __begin) {
342 _LIBCPP_ASSERT_VALID_INPUT_RANGE(
343 (__end - __begin) >= 0, "std::string_view::string_view(iterator, sentinel) received invalid range");
344 }
345# endif // _LIBCPP_STD_VER >= 20
346
347# if _LIBCPP_STD_VER >= 23
348 template <class _Range>
349 requires(!is_same_v<remove_cvref_t<_Range>, basic_string_view> && ranges::contiguous_range<_Range> &&
350 ranges::sized_range<_Range> && is_same_v<ranges::range_value_t<_Range>, _CharT> &&
351 !is_convertible_v<_Range, const _CharT*> &&
352 (!requires(remove_cvref_t<_Range>& __d) { __d.operator std::basic_string_view<_CharT, _Traits>(); }))
353 constexpr explicit _LIBCPP_HIDE_FROM_ABI basic_string_view(_Range&& __r)
354 : __data_(ranges::data(__r)), __size_(ranges::size(__r)) {}
355# endif // _LIBCPP_STD_VER >= 23
356
357 _LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI basic_string_view(const _CharT* _LIBCPP_DIAGNOSE_NULLPTR __s)
358 : __data_(__s), __size_(std::__char_traits_length_checked<_Traits>(__s)) {}
359
360# if _LIBCPP_STD_VER >= 23
361 basic_string_view(nullptr_t) = delete;
362# endif
363
364 // [string.view.iterators], iterators
365 [[__nodiscard__]] _LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI const_iterator begin() const _NOEXCEPT { return cbegin(); }
366
367 [[__nodiscard__]] _LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI const_iterator end() const _NOEXCEPT { return cend(); }
368
369 [[__nodiscard__]] _LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI const_iterator cbegin() const _NOEXCEPT {
370# ifdef _LIBCPP_ABI_BOUNDED_ITERATORS
371 return std::__make_bounded_iter(data(), data(), data() + size());
372# else
373 return const_iterator(__data_);
374# endif
375 }
376
377 [[__nodiscard__]] _LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI const_iterator cend() const _NOEXCEPT {
378# ifdef _LIBCPP_ABI_BOUNDED_ITERATORS
379 return std::__make_bounded_iter(data() + size(), data(), data() + size());
380# else
381 return const_iterator(__data_ + __size_);
382# endif
383 }
384
385 [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX17 _LIBCPP_HIDE_FROM_ABI const_reverse_iterator
386 rbegin() const _NOEXCEPT {
387 return const_reverse_iterator(cend());
388 }
389
390 [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX17 _LIBCPP_HIDE_FROM_ABI const_reverse_iterator rend() const _NOEXCEPT {
391 return const_reverse_iterator(cbegin());
392 }
393
394 [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX17 _LIBCPP_HIDE_FROM_ABI const_reverse_iterator
395 crbegin() const _NOEXCEPT {
396 return const_reverse_iterator(cend());
397 }
398
399 [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX17 _LIBCPP_HIDE_FROM_ABI const_reverse_iterator crend() const _NOEXCEPT {
400 return const_reverse_iterator(cbegin());
401 }
402
403 // [string.view.capacity], capacity
404 [[__nodiscard__]] _LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT { return __size_; }
405
406 [[__nodiscard__]] _LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI size_type length() const _NOEXCEPT { return __size_; }
407
408 [[__nodiscard__]] _LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI size_type max_size() const _NOEXCEPT {
409 return numeric_limits<size_type>::max() / sizeof(value_type);
410 }
411
412 [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool empty() const _NOEXCEPT { return __size_ == 0; }
413
414 // [string.view.access], element access
415 [[__nodiscard__]] _LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI const_reference
416 operator[](size_type __pos) const _NOEXCEPT {
417 return _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__pos < size(), "string_view[] index out of bounds"), __data_[__pos];
418 }
419
420 [[__nodiscard__]] _LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI const_reference at(size_type __pos) const {
421 return __pos >= size() ? (__throw_out_of_range(msg: "string_view::at"), __data_[0]) : __data_[__pos];
422 }
423
424 [[__nodiscard__]] _LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI const_reference front() const _NOEXCEPT {
425 return _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "string_view::front(): string is empty"), __data_[0];
426 }
427
428 [[__nodiscard__]] _LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI const_reference back() const _NOEXCEPT {
429 return _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "string_view::back(): string is empty"), __data_[__size_ - 1];
430 }
431
432 [[__nodiscard__]] _LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI const_pointer data() const _NOEXCEPT { return __data_; }
433
434 // [string.view.modifiers], modifiers:
435 _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI void remove_prefix(size_type __n) _NOEXCEPT {
436 _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__n <= size(), "remove_prefix() can't remove more than size()");
437 __data_ += __n;
438 __size_ -= __n;
439 }
440
441 _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI void remove_suffix(size_type __n) _NOEXCEPT {
442 _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__n <= size(), "remove_suffix() can't remove more than size()");
443 __size_ -= __n;
444 }
445
446 _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI void swap(basic_string_view& __other) _NOEXCEPT {
447 const value_type* __p = __data_;
448 __data_ = __other.__data_;
449 __other.__data_ = __p;
450
451 size_type __sz = __size_;
452 __size_ = __other.__size_;
453 __other.__size_ = __sz;
454 }
455
456 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type
457 copy(_CharT* __s, size_type __n, size_type __pos = 0) const {
458 if (__pos > size())
459 std::__throw_out_of_range(msg: "string_view::copy");
460 size_type __rlen = std::min(__n, size() - __pos);
461 _Traits::copy(__s, data() + __pos, __rlen);
462 return __rlen;
463 }
464
465 [[__nodiscard__]] _LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI basic_string_view
466 substr(size_type __pos = 0, size_type __n = npos) const {
467 // Use the `__assume_valid` form of the constructor to avoid an unnecessary check. Any substring of a view is a
468 // valid view. In particular, `size()` is known to be smaller than `numeric_limits<difference_type>::max()`, so the
469 // new size is also smaller. See also https://llvm.org/PR91634.
470 return __pos > size() ? (__throw_out_of_range(msg: "string_view::substr"), basic_string_view())
471 : basic_string_view(__assume_valid(), data() + __pos, std::min(__n, size() - __pos));
472 }
473
474# if _LIBCPP_STD_VER >= 26
475 [[nodiscard]]
476 _LIBCPP_HIDE_FROM_ABI constexpr basic_string_view subview(size_type __pos = 0, size_type __n = npos) const {
477 return substr(__pos, __n);
478 }
479# endif
480
481 [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX14 int compare(basic_string_view __sv) const _NOEXCEPT {
482 size_type __rlen = std::min(size(), __sv.size());
483 int __retval = _Traits::compare(data(), __sv.data(), __rlen);
484 if (__retval == 0) // first __rlen chars matched
485 __retval = size() == __sv.size() ? 0 : (size() < __sv.size() ? -1 : 1);
486 return __retval;
487 }
488
489 [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI int
490 compare(size_type __pos1, size_type __n1, basic_string_view __sv) const {
491 return substr(pos: __pos1, n: __n1).compare(__sv);
492 }
493
494 [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI int
495 compare(size_type __pos1, size_type __n1, basic_string_view __sv, size_type __pos2, size_type __n2) const {
496 return substr(pos: __pos1, n: __n1).compare(__sv.substr(__pos2, __n2));
497 }
498
499 [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI int
500 compare(const _CharT* _LIBCPP_DIAGNOSE_NULLPTR __s) const _NOEXCEPT {
501 return compare(basic_string_view(__s));
502 }
503
504 [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI int
505 compare(size_type __pos1, size_type __n1, const _CharT* _LIBCPP_DIAGNOSE_NULLPTR __s) const {
506 return substr(pos: __pos1, n: __n1).compare(basic_string_view(__s));
507 }
508
509 [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI int
510 compare(size_type __pos1, size_type __n1, const _CharT* __s, size_type __n2) const
511 _LIBCPP_DIAGNOSE_NULLPTR_IF(__n2 != 0 && __s == nullptr, " if n2 is not zero") {
512 return substr(pos: __pos1, n: __n1).compare(basic_string_view(__s, __n2));
513 }
514
515 // find
516 [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI size_type
517 find(basic_string_view __s, size_type __pos = 0) const _NOEXCEPT {
518 return std::__str_find<value_type, size_type, traits_type, npos>(data(), size(), __s.data(), __pos, __s.size());
519 }
520
521 [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI size_type
522 find(_CharT __c, size_type __pos = 0) const _NOEXCEPT {
523 return std::__str_find<value_type, size_type, traits_type, npos>(data(), size(), __c, __pos);
524 }
525
526 [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI size_type
527 find(const _CharT* __s, size_type __pos, size_type __n) const _NOEXCEPT
528 _LIBCPP_DIAGNOSE_NULLPTR_IF(__n != 0 && __s == nullptr, " if n is not zero") {
529 _LIBCPP_ASSERT_NON_NULL(__n == 0 || __s != nullptr, "string_view::find(): received nullptr");
530 return std::__str_find<value_type, size_type, traits_type, npos>(data(), size(), __s, __pos, __n);
531 }
532
533 [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI size_type
534 find(const _CharT* _LIBCPP_DIAGNOSE_NULLPTR __s, size_type __pos = 0) const _NOEXCEPT {
535 _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "string_view::find(): received nullptr");
536 return std::__str_find<value_type, size_type, traits_type, npos>(
537 data(), size(), __s, __pos, traits_type::length(__s));
538 }
539
540 // rfind
541 [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI size_type
542 rfind(basic_string_view __s, size_type __pos = npos) const _NOEXCEPT {
543 return std::__str_rfind<value_type, size_type, traits_type, npos>(data(), size(), __s.data(), __pos, __s.size());
544 }
545
546 [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI size_type
547 rfind(_CharT __c, size_type __pos = npos) const _NOEXCEPT {
548 return std::__str_rfind<value_type, size_type, traits_type, npos>(data(), size(), __c, __pos);
549 }
550
551 [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI size_type
552 rfind(const _CharT* __s, size_type __pos, size_type __n) const _NOEXCEPT
553 _LIBCPP_DIAGNOSE_NULLPTR_IF(__n != 0 && __s == nullptr, " if n is not zero") {
554 _LIBCPP_ASSERT_NON_NULL(__n == 0 || __s != nullptr, "string_view::rfind(): received nullptr");
555 return std::__str_rfind<value_type, size_type, traits_type, npos>(data(), size(), __s, __pos, __n);
556 }
557
558 [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI size_type
559 rfind(const _CharT* _LIBCPP_DIAGNOSE_NULLPTR __s, size_type __pos = npos) const _NOEXCEPT {
560 _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "string_view::rfind(): received nullptr");
561 return std::__str_rfind<value_type, size_type, traits_type, npos>(
562 data(), size(), __s, __pos, traits_type::length(__s));
563 }
564
565 // find_first_of
566 [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI size_type
567 find_first_of(basic_string_view __s, size_type __pos = 0) const _NOEXCEPT {
568 return std::__str_find_first_of<value_type, size_type, traits_type, npos>(
569 data(), size(), __s.data(), __pos, __s.size());
570 }
571
572 [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI size_type
573 find_first_of(_CharT __c, size_type __pos = 0) const _NOEXCEPT {
574 return find(__c, __pos);
575 }
576
577 [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI size_type
578 find_first_of(const _CharT* __s, size_type __pos, size_type __n) const _NOEXCEPT
579 _LIBCPP_DIAGNOSE_NULLPTR_IF(__n != 0 && __s == nullptr, " if n is not zero") {
580 _LIBCPP_ASSERT_NON_NULL(__n == 0 || __s != nullptr, "string_view::find_first_of(): received nullptr");
581 return std::__str_find_first_of<value_type, size_type, traits_type, npos>(data(), size(), __s, __pos, __n);
582 }
583
584 [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI size_type
585 find_first_of(const _CharT* _LIBCPP_DIAGNOSE_NULLPTR __s, size_type __pos = 0) const _NOEXCEPT {
586 _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "string_view::find_first_of(): received nullptr");
587 return std::__str_find_first_of<value_type, size_type, traits_type, npos>(
588 data(), size(), __s, __pos, traits_type::length(__s));
589 }
590
591 // find_last_of
592 [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI size_type
593 find_last_of(basic_string_view __s, size_type __pos = npos) const _NOEXCEPT {
594 return std::__str_find_last_of<value_type, size_type, traits_type, npos>(
595 data(), size(), __s.data(), __pos, __s.size());
596 }
597
598 [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI size_type
599 find_last_of(_CharT __c, size_type __pos = npos) const _NOEXCEPT {
600 return rfind(__c, __pos);
601 }
602
603 [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI size_type
604 find_last_of(const _CharT* __s, size_type __pos, size_type __n) const _NOEXCEPT
605 _LIBCPP_DIAGNOSE_NULLPTR_IF(__n != 0 && __s == nullptr, " if n is not zero") {
606 _LIBCPP_ASSERT_NON_NULL(__n == 0 || __s != nullptr, "string_view::find_last_of(): received nullptr");
607 return std::__str_find_last_of<value_type, size_type, traits_type, npos>(data(), size(), __s, __pos, __n);
608 }
609
610 [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI size_type
611 find_last_of(const _CharT* _LIBCPP_DIAGNOSE_NULLPTR __s, size_type __pos = npos) const _NOEXCEPT {
612 _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "string_view::find_last_of(): received nullptr");
613 return std::__str_find_last_of<value_type, size_type, traits_type, npos>(
614 data(), size(), __s, __pos, traits_type::length(__s));
615 }
616
617 // find_first_not_of
618 [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI size_type
619 find_first_not_of(basic_string_view __s, size_type __pos = 0) const _NOEXCEPT {
620 return std::__str_find_first_not_of<value_type, size_type, traits_type, npos>(
621 data(), size(), __s.data(), __pos, __s.size());
622 }
623
624 [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI size_type
625 find_first_not_of(_CharT __c, size_type __pos = 0) const _NOEXCEPT {
626 return std::__str_find_first_not_of<value_type, size_type, traits_type, npos>(data(), size(), __c, __pos);
627 }
628
629 [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI size_type
630 find_first_not_of(const _CharT* __s, size_type __pos, size_type __n) const _NOEXCEPT
631 _LIBCPP_DIAGNOSE_NULLPTR_IF(__n != 0 && __s == nullptr, " if n is not zero") {
632 _LIBCPP_ASSERT_NON_NULL(__n == 0 || __s != nullptr, "string_view::find_first_not_of(): received nullptr");
633 return std::__str_find_first_not_of<value_type, size_type, traits_type, npos>(data(), size(), __s, __pos, __n);
634 }
635
636 [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI size_type
637 find_first_not_of(const _CharT* _LIBCPP_DIAGNOSE_NULLPTR __s, size_type __pos = 0) const _NOEXCEPT {
638 _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "string_view::find_first_not_of(): received nullptr");
639 return std::__str_find_first_not_of<value_type, size_type, traits_type, npos>(
640 data(), size(), __s, __pos, traits_type::length(__s));
641 }
642
643 // find_last_not_of
644 [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI size_type
645 find_last_not_of(basic_string_view __s, size_type __pos = npos) const _NOEXCEPT {
646 return std::__str_find_last_not_of<value_type, size_type, traits_type, npos>(
647 data(), size(), __s.data(), __pos, __s.size());
648 }
649
650 [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI size_type
651 find_last_not_of(_CharT __c, size_type __pos = npos) const _NOEXCEPT {
652 return std::__str_find_last_not_of<value_type, size_type, traits_type, npos>(data(), size(), __c, __pos);
653 }
654
655 [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI size_type
656 find_last_not_of(const _CharT* __s, size_type __pos, size_type __n) const _NOEXCEPT
657 _LIBCPP_DIAGNOSE_NULLPTR_IF(__n != 0 && __s == nullptr, " if n is not zero") {
658 _LIBCPP_ASSERT_NON_NULL(__n == 0 || __s != nullptr, "string_view::find_last_not_of(): received nullptr");
659 return std::__str_find_last_not_of<value_type, size_type, traits_type, npos>(data(), size(), __s, __pos, __n);
660 }
661
662 [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI size_type
663 find_last_not_of(const _CharT* _LIBCPP_DIAGNOSE_NULLPTR __s, size_type __pos = npos) const _NOEXCEPT {
664 _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "string_view::find_last_not_of(): received nullptr");
665 return std::__str_find_last_not_of<value_type, size_type, traits_type, npos>(
666 data(), size(), __s, __pos, traits_type::length(__s));
667 }
668
669# if _LIBCPP_STD_VER >= 20
670 [[nodiscard]] constexpr _LIBCPP_HIDE_FROM_ABI bool starts_with(basic_string_view __s) const noexcept {
671 return size() >= __s.size() && compare(0, __s.size(), __s) == 0;
672 }
673
674 [[nodiscard]] constexpr _LIBCPP_HIDE_FROM_ABI bool starts_with(value_type __c) const noexcept {
675 return !empty() && _Traits::eq(front(), __c);
676 }
677
678 [[nodiscard]] constexpr _LIBCPP_HIDE_FROM_ABI bool
679 starts_with(const value_type* _LIBCPP_DIAGNOSE_NULLPTR __s) const noexcept {
680 return starts_with(basic_string_view(__s));
681 }
682
683 [[nodiscard]] constexpr _LIBCPP_HIDE_FROM_ABI bool ends_with(basic_string_view __s) const noexcept {
684 return size() >= __s.size() && compare(size() - __s.size(), npos, __s) == 0;
685 }
686
687 [[nodiscard]] constexpr _LIBCPP_HIDE_FROM_ABI bool ends_with(value_type __c) const noexcept {
688 return !empty() && _Traits::eq(back(), __c);
689 }
690
691 [[nodiscard]] constexpr _LIBCPP_HIDE_FROM_ABI bool
692 ends_with(const value_type* _LIBCPP_DIAGNOSE_NULLPTR __s) const noexcept {
693 return ends_with(basic_string_view(__s));
694 }
695# endif
696
697# if _LIBCPP_STD_VER >= 23
698 [[nodiscard]] constexpr _LIBCPP_HIDE_FROM_ABI bool contains(basic_string_view __sv) const noexcept {
699 return find(__sv) != npos;
700 }
701
702 [[nodiscard]] constexpr _LIBCPP_HIDE_FROM_ABI bool contains(value_type __c) const noexcept {
703 return find(__c) != npos;
704 }
705
706 [[nodiscard]] constexpr _LIBCPP_HIDE_FROM_ABI bool contains(const value_type* _LIBCPP_DIAGNOSE_NULLPTR __s) const {
707 return find(__s) != npos;
708 }
709# endif
710
711private:
712 struct __assume_valid {};
713
714 // This is the same as the pointer and length constructor, but without the additional hardening checks. It is intended
715 // for use within the class, when the class invariants already guarantee the resulting object is valid. The compiler
716 // usually cannot eliminate the redundant checks because it does not know class invariants.
717 _LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI
718 basic_string_view(__assume_valid, const _CharT* __s, size_type __len) _NOEXCEPT
719 : __data_(__s),
720 __size_(__len) {}
721
722 const value_type* __data_;
723 size_type __size_;
724
725 template <class, class, class>
726 friend class basic_string;
727};
728_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(basic_string_view);
729
730# if _LIBCPP_STD_VER >= 20
731template <class _CharT, class _Traits>
732inline constexpr bool ranges::enable_view<basic_string_view<_CharT, _Traits>> = true;
733
734template <class _CharT, class _Traits>
735inline constexpr bool ranges::enable_borrowed_range<basic_string_view<_CharT, _Traits> > = true;
736# endif // _LIBCPP_STD_VER >= 20
737
738// [string.view.deduct]
739
740# if _LIBCPP_STD_VER >= 20
741template <contiguous_iterator _It, sized_sentinel_for<_It> _End>
742basic_string_view(_It, _End) -> basic_string_view<iter_value_t<_It>>;
743# endif // _LIBCPP_STD_VER >= 20
744
745# if _LIBCPP_STD_VER >= 23
746template <ranges::contiguous_range _Range>
747basic_string_view(_Range) -> basic_string_view<ranges::range_value_t<_Range>>;
748# endif
749
750// [string.view.comparison]
751
752// The dummy default template parameters are used to work around a MSVC issue with mangling, see VSO-409326 for details.
753// This applies to the other sufficient overloads below for the other comparison operators.
754template <class _CharT, class _Traits, int = 1>
755_LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI bool
756operator==(basic_string_view<_CharT, _Traits> __lhs,
757 __type_identity_t<basic_string_view<_CharT, _Traits> > __rhs) _NOEXCEPT {
758 if (__lhs.size() != __rhs.size())
759 return false;
760 return __lhs.compare(__rhs) == 0;
761}
762
763# if _LIBCPP_STD_VER >= 20
764
765template <class _CharT, class _Traits>
766_LIBCPP_HIDE_FROM_ABI constexpr auto operator<=>(basic_string_view<_CharT, _Traits> __lhs,
767 type_identity_t<basic_string_view<_CharT, _Traits>> __rhs) noexcept {
768 if constexpr (requires { typename _Traits::comparison_category; }) {
769 // [string.view]/4
770 static_assert(
771 __comparison_category<typename _Traits::comparison_category>, "return type is not a comparison category type");
772 return static_cast<typename _Traits::comparison_category>(__lhs.compare(__rhs) <=> 0);
773 } else {
774 return static_cast<weak_ordering>(__lhs.compare(__rhs) <=> 0);
775 }
776}
777
778# else
779
780// operator ==
781
782template <class _CharT, class _Traits>
783_LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI bool
784operator==(basic_string_view<_CharT, _Traits> __lhs, basic_string_view<_CharT, _Traits> __rhs) _NOEXCEPT {
785 if (__lhs.size() != __rhs.size())
786 return false;
787 return __lhs.compare(__rhs) == 0;
788}
789
790template <class _CharT, class _Traits, int = 2>
791_LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI bool
792operator==(__type_identity_t<basic_string_view<_CharT, _Traits> > __lhs,
793 basic_string_view<_CharT, _Traits> __rhs) _NOEXCEPT {
794 return __lhs == __rhs;
795}
796
797// operator !=
798template <class _CharT, class _Traits>
799_LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI bool
800operator!=(basic_string_view<_CharT, _Traits> __lhs, basic_string_view<_CharT, _Traits> __rhs) _NOEXCEPT {
801 return !(__lhs == __rhs);
802}
803
804template <class _CharT, class _Traits, int = 1>
805_LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI bool
806operator!=(basic_string_view<_CharT, _Traits> __lhs,
807 __type_identity_t<basic_string_view<_CharT, _Traits> > __rhs) _NOEXCEPT {
808 return !(__lhs == __rhs);
809}
810
811template <class _CharT, class _Traits, int = 2>
812_LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI bool
813operator!=(__type_identity_t<basic_string_view<_CharT, _Traits> > __lhs,
814 basic_string_view<_CharT, _Traits> __rhs) _NOEXCEPT {
815 return !(__lhs == __rhs);
816}
817
818// operator <
819template <class _CharT, class _Traits>
820_LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI bool
821operator<(basic_string_view<_CharT, _Traits> __lhs, basic_string_view<_CharT, _Traits> __rhs) _NOEXCEPT {
822 return __lhs.compare(__rhs) < 0;
823}
824
825template <class _CharT, class _Traits, int = 1>
826_LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI bool
827operator<(basic_string_view<_CharT, _Traits> __lhs,
828 __type_identity_t<basic_string_view<_CharT, _Traits> > __rhs) _NOEXCEPT {
829 return __lhs.compare(__rhs) < 0;
830}
831
832template <class _CharT, class _Traits, int = 2>
833_LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI bool
834operator<(__type_identity_t<basic_string_view<_CharT, _Traits> > __lhs,
835 basic_string_view<_CharT, _Traits> __rhs) _NOEXCEPT {
836 return __lhs.compare(__rhs) < 0;
837}
838
839// operator >
840template <class _CharT, class _Traits>
841_LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI bool
842operator>(basic_string_view<_CharT, _Traits> __lhs, basic_string_view<_CharT, _Traits> __rhs) _NOEXCEPT {
843 return __lhs.compare(__rhs) > 0;
844}
845
846template <class _CharT, class _Traits, int = 1>
847_LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI bool
848operator>(basic_string_view<_CharT, _Traits> __lhs,
849 __type_identity_t<basic_string_view<_CharT, _Traits> > __rhs) _NOEXCEPT {
850 return __lhs.compare(__rhs) > 0;
851}
852
853template <class _CharT, class _Traits, int = 2>
854_LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI bool
855operator>(__type_identity_t<basic_string_view<_CharT, _Traits> > __lhs,
856 basic_string_view<_CharT, _Traits> __rhs) _NOEXCEPT {
857 return __lhs.compare(__rhs) > 0;
858}
859
860// operator <=
861template <class _CharT, class _Traits>
862_LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI bool
863operator<=(basic_string_view<_CharT, _Traits> __lhs, basic_string_view<_CharT, _Traits> __rhs) _NOEXCEPT {
864 return __lhs.compare(__rhs) <= 0;
865}
866
867template <class _CharT, class _Traits, int = 1>
868_LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI bool
869operator<=(basic_string_view<_CharT, _Traits> __lhs,
870 __type_identity_t<basic_string_view<_CharT, _Traits> > __rhs) _NOEXCEPT {
871 return __lhs.compare(__rhs) <= 0;
872}
873
874template <class _CharT, class _Traits, int = 2>
875_LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI bool
876operator<=(__type_identity_t<basic_string_view<_CharT, _Traits> > __lhs,
877 basic_string_view<_CharT, _Traits> __rhs) _NOEXCEPT {
878 return __lhs.compare(__rhs) <= 0;
879}
880
881// operator >=
882template <class _CharT, class _Traits>
883_LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI bool
884operator>=(basic_string_view<_CharT, _Traits> __lhs, basic_string_view<_CharT, _Traits> __rhs) _NOEXCEPT {
885 return __lhs.compare(__rhs) >= 0;
886}
887
888template <class _CharT, class _Traits, int = 1>
889_LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI bool
890operator>=(basic_string_view<_CharT, _Traits> __lhs,
891 __type_identity_t<basic_string_view<_CharT, _Traits> > __rhs) _NOEXCEPT {
892 return __lhs.compare(__rhs) >= 0;
893}
894
895template <class _CharT, class _Traits, int = 2>
896_LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI bool
897operator>=(__type_identity_t<basic_string_view<_CharT, _Traits> > __lhs,
898 basic_string_view<_CharT, _Traits> __rhs) _NOEXCEPT {
899 return __lhs.compare(__rhs) >= 0;
900}
901
902# endif // _LIBCPP_STD_VER >= 20
903
904template <class _CharT, class _Traits>
905_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>&
906operator<<(basic_ostream<_CharT, _Traits>& __os, basic_string_view<_CharT, _Traits> __str);
907
908// [string.view.hash]
909template <class _CharT>
910struct __string_view_hash : public __unary_function<basic_string_view<_CharT, char_traits<_CharT> >, size_t> {
911 [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_t
912 operator()(const basic_string_view<_CharT, char_traits<_CharT> > __val) const _NOEXCEPT {
913 return std::__do_string_hash(__val.data(), __val.data() + __val.size());
914 }
915};
916
917template <>
918struct hash<basic_string_view<char, char_traits<char> > > : __string_view_hash<char> {};
919
920# if _LIBCPP_HAS_CHAR8_T
921template <>
922struct hash<basic_string_view<char8_t, char_traits<char8_t> > > : __string_view_hash<char8_t> {};
923# endif
924
925template <>
926struct hash<basic_string_view<char16_t, char_traits<char16_t> > > : __string_view_hash<char16_t> {};
927
928template <>
929struct hash<basic_string_view<char32_t, char_traits<char32_t> > > : __string_view_hash<char32_t> {};
930
931# if _LIBCPP_HAS_WIDE_CHARACTERS
932template <>
933struct hash<basic_string_view<wchar_t, char_traits<wchar_t> > > : __string_view_hash<wchar_t> {};
934# endif
935
936# if _LIBCPP_STD_VER >= 14
937inline namespace literals {
938inline namespace string_view_literals {
939[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI constexpr basic_string_view<char>
940operator""sv(const char* __str, size_t __len) noexcept {
941 return basic_string_view<char>(__str, __len);
942}
943
944# if _LIBCPP_HAS_WIDE_CHARACTERS
945[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI constexpr basic_string_view<wchar_t>
946operator""sv(const wchar_t* __str, size_t __len) noexcept {
947 return basic_string_view<wchar_t>(__str, __len);
948}
949# endif
950
951# if _LIBCPP_HAS_CHAR8_T
952[[nodiscard]] inline _LIBCPP_HIDE_FROM_ABI constexpr basic_string_view<char8_t>
953operator""sv(const char8_t* __str, size_t __len) noexcept {
954 return basic_string_view<char8_t>(__str, __len);
955}
956# endif
957
958[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI constexpr basic_string_view<char16_t>
959operator""sv(const char16_t* __str, size_t __len) noexcept {
960 return basic_string_view<char16_t>(__str, __len);
961}
962
963[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI constexpr basic_string_view<char32_t>
964operator""sv(const char32_t* __str, size_t __len) noexcept {
965 return basic_string_view<char32_t>(__str, __len);
966}
967} // namespace string_view_literals
968} // namespace literals
969# endif
970_LIBCPP_END_NAMESPACE_STD
971
972_LIBCPP_POP_MACROS
973
974# if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20
975# include <algorithm>
976# include <concepts>
977# include <cstdlib>
978# include <iterator>
979# include <optional>
980# include <type_traits>
981# endif
982#endif // __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)
983
984#endif // _LIBCPP_STRING_VIEW
985