libstdc++
string_view
Go to the documentation of this file.
1 // Components for manipulating non-owning sequences of characters -*- C++ -*-
2 
3 // Copyright (C) 2013-2025 Free Software Foundation, Inc.
4 //
5 // This file is part of the GNU ISO C++ Library. This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 3, or (at your option)
9 // any later version.
10 
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 
16 // Under Section 7 of GPL version 3, you are granted additional
17 // permissions described in the GCC Runtime Library Exception, version
18 // 3.1, as published by the Free Software Foundation.
19 
20 // You should have received a copy of the GNU General Public License and
21 // a copy of the GCC Runtime Library Exception along with this program;
22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 // <http://www.gnu.org/licenses/>.
24 
25 /** @file include/string_view
26  * This is a Standard C++ Library header.
27  */
28 
29 //
30 // N3762 basic_string_view library
31 //
32 
33 #ifndef _GLIBCXX_STRING_VIEW
34 #define _GLIBCXX_STRING_VIEW 1
35 
36 #ifdef _GLIBCXX_SYSHDR
37 #pragma GCC system_header
38 #endif
39 
40 #define __glibcxx_want_constexpr_char_traits
41 #define __glibcxx_want_constexpr_string_view
42 #define __glibcxx_want_freestanding_string_view
43 #define __glibcxx_want_string_view
44 #define __glibcxx_want_starts_ends_with
45 #define __glibcxx_want_string_contains
46 #include <bits/version.h>
47 
48 #if __cplusplus >= 201703L
49 
50 #include <bits/char_traits.h>
51 #include <bits/functexcept.h>
52 #include <bits/functional_hash.h>
53 #include <bits/range_access.h>
54 #include <bits/stl_algobase.h>
55 #include <ext/numeric_traits.h>
56 
57 #if __cplusplus >= 202002L
58 # include <bits/ranges_base.h>
59 #endif
60 
61 #if _GLIBCXX_HOSTED
62 # include <iosfwd>
63 # include <bits/ostream_insert.h>
64 #endif
65 
66 namespace std _GLIBCXX_VISIBILITY(default)
67 {
68 _GLIBCXX_BEGIN_NAMESPACE_VERSION
69 
70  // Helper for basic_string and basic_string_view members.
71  constexpr size_t
72  __sv_check(size_t __size, size_t __pos, const char* __s)
73  {
74  if (__pos > __size)
75  __throw_out_of_range_fmt(__N("%s: __pos (which is %zu) > __size "
76  "(which is %zu)"), __s, __pos, __size);
77  return __pos;
78  }
79 
80  // Helper for basic_string members.
81  // NB: __sv_limit doesn't check for a bad __pos value.
82  constexpr size_t
83  __sv_limit(size_t __size, size_t __pos, size_t __off) noexcept
84  {
85  const bool __testoff = __off < __size - __pos;
86  return __testoff ? __off : __size - __pos;
87  }
88 
89  /**
90  * @class basic_string_view <string_view>
91  * @brief A non-owning reference to a string.
92  *
93  * @ingroup strings
94  * @ingroup sequences
95  *
96  * @tparam _CharT Type of character
97  * @tparam _Traits Traits for character type, defaults to
98  * char_traits<_CharT>.
99  *
100  * A basic_string_view looks like this:
101  *
102  * @code
103  * _CharT* _M_str
104  * size_t _M_len
105  * @endcode
106  */
107  template<typename _CharT, typename _Traits = std::char_traits<_CharT>>
108  class basic_string_view
109  {
110  static_assert(!is_array_v<_CharT>);
111  static_assert(is_trivially_copyable_v<_CharT>
112  && is_trivially_default_constructible_v<_CharT>
113  && is_standard_layout_v<_CharT>);
114  static_assert(is_same_v<_CharT, typename _Traits::char_type>);
115 
116  public:
117 
118  // types
119  using traits_type = _Traits;
120  using value_type = _CharT;
121  using pointer = value_type*;
122  using const_pointer = const value_type*;
123  using reference = value_type&;
124  using const_reference = const value_type&;
125  using const_iterator = const value_type*;
126  using iterator = const_iterator;
127  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
128  using reverse_iterator = const_reverse_iterator;
129  using size_type = size_t;
130  using difference_type = ptrdiff_t;
131  static constexpr size_type npos = size_type(-1);
132 
133  // [string.view.cons], construction and assignment
134 
135  constexpr
136  basic_string_view() noexcept
137  : _M_len{0}, _M_str{nullptr}
138  { }
139 
140  constexpr basic_string_view(const basic_string_view&) noexcept = default;
141 
142  [[__gnu__::__nonnull__]]
143  constexpr
144  basic_string_view(const _CharT* __str) noexcept
145  : _M_len{traits_type::length(__str)},
146  _M_str{__str}
147  { }
148 
149  constexpr
150  basic_string_view(const _CharT* __str, size_type __len) noexcept
151  : _M_len{__len}, _M_str{__str}
152  { }
153 
154 #if __cplusplus >= 202002L && __cpp_lib_concepts
155  template<contiguous_iterator _It, sized_sentinel_for<_It> _End>
156  requires same_as<iter_value_t<_It>, _CharT>
157  && (!convertible_to<_End, size_type>)
158  constexpr
159  basic_string_view(_It __first, _End __last)
160  noexcept(noexcept(__last - __first))
161  : _M_len(__last - __first), _M_str(std::to_address(__first))
162  { }
163 
164 #if __cplusplus > 202002L
165  template<typename _Range, typename _DRange = remove_cvref_t<_Range>>
166  requires (!is_same_v<_DRange, basic_string_view>)
167  && ranges::contiguous_range<_Range>
168  && ranges::sized_range<_Range>
169  && is_same_v<ranges::range_value_t<_Range>, _CharT>
170  && (!is_convertible_v<_Range, const _CharT*>)
171  && (!requires (_DRange& __d) {
172  __d.operator ::std::basic_string_view<_CharT, _Traits>();
173  })
174  constexpr explicit
175  basic_string_view(_Range&& __r)
176  noexcept(noexcept(ranges::size(__r)) && noexcept(ranges::data(__r)))
177  : _M_len(ranges::size(__r)), _M_str(ranges::data(__r))
178  { }
179 
180  basic_string_view(nullptr_t) = delete;
181 #endif // C++23
182 #endif // C++20
183 
184  constexpr basic_string_view&
185  operator=(const basic_string_view&) noexcept = default;
186 
187  // [string.view.iterators], iterator support
188 
189  [[nodiscard]]
190  constexpr const_iterator
191  begin() const noexcept
192  { return this->_M_str; }
193 
194  [[nodiscard]]
195  constexpr const_iterator
196  end() const noexcept
197  { return this->_M_str + this->_M_len; }
198 
199  [[nodiscard]]
200  constexpr const_iterator
201  cbegin() const noexcept
202  { return this->_M_str; }
203 
204  [[nodiscard]]
205  constexpr const_iterator
206  cend() const noexcept
207  { return this->_M_str + this->_M_len; }
208 
209  [[nodiscard]]
210  constexpr const_reverse_iterator
211  rbegin() const noexcept
212  { return const_reverse_iterator(this->end()); }
213 
214  [[nodiscard]]
215  constexpr const_reverse_iterator
216  rend() const noexcept
217  { return const_reverse_iterator(this->begin()); }
218 
219  [[nodiscard]]
220  constexpr const_reverse_iterator
221  crbegin() const noexcept
222  { return const_reverse_iterator(this->end()); }
223 
224  [[nodiscard]]
225  constexpr const_reverse_iterator
226  crend() const noexcept
227  { return const_reverse_iterator(this->begin()); }
228 
229  // [string.view.capacity], capacity
230 
231  [[nodiscard]]
232  constexpr size_type
233  size() const noexcept
234  { return this->_M_len; }
235 
236  [[nodiscard]]
237  constexpr size_type
238  length() const noexcept
239  { return _M_len; }
240 
241  [[nodiscard]]
242  constexpr size_type
243  max_size() const noexcept
244  {
245  return (npos - sizeof(size_type) - sizeof(void*))
246  / sizeof(value_type) / 4;
247  }
248 
249  [[nodiscard]]
250  constexpr bool
251  empty() const noexcept
252  { return this->_M_len == 0; }
253 
254  // [string.view.access], element access
255 
256  [[nodiscard]]
257  constexpr const_reference
258  operator[](size_type __pos) const noexcept
259  {
260  __glibcxx_assert(__pos < this->_M_len);
261  return *(this->_M_str + __pos);
262  }
263 
264  [[nodiscard]]
265  constexpr const_reference
266  at(size_type __pos) const
267  {
268  if (__pos >= _M_len)
269  __throw_out_of_range_fmt(__N("basic_string_view::at: __pos "
270  "(which is %zu) >= this->size() "
271  "(which is %zu)"), __pos, this->size());
272  return *(this->_M_str + __pos);
273  }
274 
275  [[nodiscard]]
276  constexpr const_reference
277  front() const noexcept
278  {
279  __glibcxx_assert(this->_M_len > 0);
280  return *this->_M_str;
281  }
282 
283  [[nodiscard]]
284  constexpr const_reference
285  back() const noexcept
286  {
287  __glibcxx_assert(this->_M_len > 0);
288  return *(this->_M_str + this->_M_len - 1);
289  }
290 
291  [[nodiscard]]
292  constexpr const_pointer
293  data() const noexcept
294  { return this->_M_str; }
295 
296  // [string.view.modifiers], modifiers:
297 
298  constexpr void
299  remove_prefix(size_type __n) noexcept
300  {
301  __glibcxx_assert(this->_M_len >= __n);
302  this->_M_str += __n;
303  this->_M_len -= __n;
304  }
305 
306  constexpr void
307  remove_suffix(size_type __n) noexcept
308  {
309  __glibcxx_assert(this->_M_len >= __n);
310  this->_M_len -= __n;
311  }
312 
313  constexpr void
314  swap(basic_string_view& __sv) noexcept
315  {
316  auto __tmp = *this;
317  *this = __sv;
318  __sv = __tmp;
319  }
320 
321  // [string.view.ops], string operations:
322 
323  _GLIBCXX20_CONSTEXPR
324  size_type
325  copy(_CharT* __str, size_type __n, size_type __pos = 0) const
326  {
327  __glibcxx_requires_string_len(__str, __n);
328  __pos = std::__sv_check(size(), __pos, "basic_string_view::copy");
329  const size_type __rlen = std::min<size_t>(__n, _M_len - __pos);
330  // _GLIBCXX_RESOLVE_LIB_DEFECTS
331  // 2777. basic_string_view::copy should use char_traits::copy
332  traits_type::copy(__str, data() + __pos, __rlen);
333  return __rlen;
334  }
335 
336  [[nodiscard]]
337  constexpr basic_string_view
338  substr(size_type __pos = 0, size_type __n = npos) const noexcept(false)
339  {
340  __pos = std::__sv_check(size(), __pos, "basic_string_view::substr");
341  const size_type __rlen = std::min<size_t>(__n, _M_len - __pos);
342  return basic_string_view{_M_str + __pos, __rlen};
343  }
344 
345  [[nodiscard]]
346  constexpr int
347  compare(basic_string_view __str) const noexcept
348  {
349  const size_type __rlen = std::min(this->_M_len, __str._M_len);
350  int __ret = traits_type::compare(this->_M_str, __str._M_str, __rlen);
351  if (__ret == 0)
352  __ret = _S_compare(this->_M_len, __str._M_len);
353  return __ret;
354  }
355 
356  [[nodiscard]]
357  constexpr int
358  compare(size_type __pos1, size_type __n1, basic_string_view __str) const
359  { return this->substr(__pos1, __n1).compare(__str); }
360 
361  [[nodiscard]]
362  constexpr int
363  compare(size_type __pos1, size_type __n1,
364  basic_string_view __str, size_type __pos2, size_type __n2) const
365  {
366  return this->substr(__pos1, __n1).compare(__str.substr(__pos2, __n2));
367  }
368 
369  [[nodiscard, __gnu__::__nonnull__]]
370  constexpr int
371  compare(const _CharT* __str) const noexcept
372  { return this->compare(basic_string_view{__str}); }
373 
374  [[nodiscard, __gnu__::__nonnull__]]
375  constexpr int
376  compare(size_type __pos1, size_type __n1, const _CharT* __str) const
377  { return this->substr(__pos1, __n1).compare(basic_string_view{__str}); }
378 
379  [[nodiscard]]
380  constexpr int
381  compare(size_type __pos1, size_type __n1,
382  const _CharT* __str, size_type __n2) const noexcept(false)
383  {
384  return this->substr(__pos1, __n1)
385  .compare(basic_string_view(__str, __n2));
386  }
387 
388 #ifdef __cpp_lib_starts_ends_with // C++ >= 20
389  [[nodiscard]]
390  constexpr bool
391  starts_with(basic_string_view __x) const noexcept
392  {
393  return _M_len >= __x._M_len
394  && traits_type::compare(_M_str, __x._M_str, __x._M_len) == 0;
395  }
396 
397  [[nodiscard]]
398  constexpr bool
399  starts_with(_CharT __x) const noexcept
400  { return !this->empty() && traits_type::eq(this->front(), __x); }
401 
402  [[nodiscard, __gnu__::__nonnull__]]
403  constexpr bool
404  starts_with(const _CharT* __x) const noexcept
405  { return this->starts_with(basic_string_view(__x)); }
406 
407  [[nodiscard]]
408  constexpr bool
409  ends_with(basic_string_view __x) const noexcept
410  {
411  const auto __len = this->size();
412  const auto __xlen = __x.size();
413  return __len >= __xlen
414  && traits_type::compare(end() - __xlen, __x.data(), __xlen) == 0;
415  }
416 
417  [[nodiscard]]
418  constexpr bool
419  ends_with(_CharT __x) const noexcept
420  { return !this->empty() && traits_type::eq(this->back(), __x); }
421 
422  [[nodiscard, __gnu__::__nonnull__]]
423  constexpr bool
424  ends_with(const _CharT* __x) const noexcept
425  { return this->ends_with(basic_string_view(__x)); }
426 #endif // __cpp_lib_starts_ends_with
427 
428 #if __cplusplus > 202002L
429 #if _GLIBCXX_HOSTED && !defined(__cpp_lib_string_contains)
430  // This FTM is not freestanding as it also implies matching <string>
431  // support, and <string> is omitted from the freestanding subset.
432 # error "libstdc++ bug: string_contains not defined when it should be"
433 #endif // HOSTED
434  [[nodiscard]]
435  constexpr bool
436  contains(basic_string_view __x) const noexcept
437  { return this->find(__x) != npos; }
438 
439  [[nodiscard]]
440  constexpr bool
441  contains(_CharT __x) const noexcept
442  { return this->find(__x) != npos; }
443 
444  [[nodiscard, __gnu__::__nonnull__]]
445  constexpr bool
446  contains(const _CharT* __x) const noexcept
447  { return this->find(__x) != npos; }
448 #endif // C++23
449 
450  // [string.view.find], searching
451 
452  [[nodiscard]]
453  constexpr size_type
454  find(basic_string_view __str, size_type __pos = 0) const noexcept
455  { return this->find(__str._M_str, __pos, __str._M_len); }
456 
457  [[nodiscard]]
458  constexpr size_type
459  find(_CharT __c, size_type __pos = 0) const noexcept;
460 
461  [[nodiscard]]
462  constexpr size_type
463  find(const _CharT* __str, size_type __pos, size_type __n) const noexcept;
464 
465  [[nodiscard, __gnu__::__nonnull__]]
466  constexpr size_type
467  find(const _CharT* __str, size_type __pos = 0) const noexcept
468  { return this->find(__str, __pos, traits_type::length(__str)); }
469 
470  [[nodiscard]]
471  constexpr size_type
472  rfind(basic_string_view __str, size_type __pos = npos) const noexcept
473  { return this->rfind(__str._M_str, __pos, __str._M_len); }
474 
475  [[nodiscard]]
476  constexpr size_type
477  rfind(_CharT __c, size_type __pos = npos) const noexcept;
478 
479  [[nodiscard]]
480  constexpr size_type
481  rfind(const _CharT* __str, size_type __pos, size_type __n) const noexcept;
482 
483  [[nodiscard, __gnu__::__nonnull__]]
484  constexpr size_type
485  rfind(const _CharT* __str, size_type __pos = npos) const noexcept
486  { return this->rfind(__str, __pos, traits_type::length(__str)); }
487 
488  [[nodiscard]]
489  constexpr size_type
490  find_first_of(basic_string_view __str, size_type __pos = 0) const noexcept
491  { return this->find_first_of(__str._M_str, __pos, __str._M_len); }
492 
493  [[nodiscard]]
494  constexpr size_type
495  find_first_of(_CharT __c, size_type __pos = 0) const noexcept
496  { return this->find(__c, __pos); }
497 
498  [[nodiscard]]
499  constexpr size_type
500  find_first_of(const _CharT* __str, size_type __pos,
501  size_type __n) const noexcept;
502 
503  [[nodiscard, __gnu__::__nonnull__]]
504  constexpr size_type
505  find_first_of(const _CharT* __str, size_type __pos = 0) const noexcept
506  { return this->find_first_of(__str, __pos, traits_type::length(__str)); }
507 
508  [[nodiscard]]
509  constexpr size_type
510  find_last_of(basic_string_view __str,
511  size_type __pos = npos) const noexcept
512  { return this->find_last_of(__str._M_str, __pos, __str._M_len); }
513 
514  [[nodiscard]]
515  constexpr size_type
516  find_last_of(_CharT __c, size_type __pos=npos) const noexcept
517  { return this->rfind(__c, __pos); }
518 
519  [[nodiscard]]
520  constexpr size_type
521  find_last_of(const _CharT* __str, size_type __pos,
522  size_type __n) const noexcept;
523 
524  [[nodiscard, __gnu__::__nonnull__]]
525  constexpr size_type
526  find_last_of(const _CharT* __str, size_type __pos = npos) const noexcept
527  { return this->find_last_of(__str, __pos, traits_type::length(__str)); }
528 
529  [[nodiscard]]
530  constexpr size_type
531  find_first_not_of(basic_string_view __str,
532  size_type __pos = 0) const noexcept
533  { return this->find_first_not_of(__str._M_str, __pos, __str._M_len); }
534 
535  [[nodiscard]]
536  constexpr size_type
537  find_first_not_of(_CharT __c, size_type __pos = 0) const noexcept;
538 
539  [[nodiscard]]
540  constexpr size_type
541  find_first_not_of(const _CharT* __str,
542  size_type __pos, size_type __n) const noexcept;
543 
544  [[nodiscard, __gnu__::__nonnull__]]
545  constexpr size_type
546  find_first_not_of(const _CharT* __str, size_type __pos = 0) const noexcept
547  {
548  return this->find_first_not_of(__str, __pos,
549  traits_type::length(__str));
550  }
551 
552  [[nodiscard]]
553  constexpr size_type
554  find_last_not_of(basic_string_view __str,
555  size_type __pos = npos) const noexcept
556  { return this->find_last_not_of(__str._M_str, __pos, __str._M_len); }
557 
558  [[nodiscard]]
559  constexpr size_type
560  find_last_not_of(_CharT __c, size_type __pos = npos) const noexcept;
561 
562  [[nodiscard]]
563  constexpr size_type
564  find_last_not_of(const _CharT* __str,
565  size_type __pos, size_type __n) const noexcept;
566 
567  [[nodiscard, __gnu__::__nonnull__]]
568  constexpr size_type
569  find_last_not_of(const _CharT* __str,
570  size_type __pos = npos) const noexcept
571  {
572  return this->find_last_not_of(__str, __pos,
573  traits_type::length(__str));
574  }
575 
576  private:
577 
578  static constexpr int
579  _S_compare(size_type __n1, size_type __n2) noexcept
580  {
581  using __limits = __gnu_cxx::__int_traits<int>;
582  const difference_type __diff = __n1 - __n2;
583  if (__diff > __limits::__max)
584  return __limits::__max;
585  if (__diff < __limits::__min)
586  return __limits::__min;
587  return static_cast<int>(__diff);
588  }
589 
590  size_t _M_len;
591  const _CharT* _M_str;
592  };
593 
594 #if __cplusplus > 201703L && __cpp_lib_concepts && __cpp_deduction_guides
595  template<contiguous_iterator _It, sized_sentinel_for<_It> _End>
596  basic_string_view(_It, _End) -> basic_string_view<iter_value_t<_It>>;
597 
598 #if __cplusplus > 202002L
599  template<ranges::contiguous_range _Range>
600  basic_string_view(_Range&&)
601  -> basic_string_view<ranges::range_value_t<_Range>>;
602 #endif
603 #endif
604 
605  // [string.view.comparison], non-member basic_string_view comparison function
606 
607  // Several of these functions use type_identity_t to create a non-deduced
608  // context, so that only one argument participates in template argument
609  // deduction and the other argument gets implicitly converted to the deduced
610  // type (see N3766).
611 
612 #if __cpp_lib_three_way_comparison
613  template<typename _CharT, typename _Traits>
614  [[nodiscard]]
615  constexpr bool
616  operator==(basic_string_view<_CharT, _Traits> __x,
617  type_identity_t<basic_string_view<_CharT, _Traits>> __y)
618  noexcept
619  { return __x.size() == __y.size() && __x.compare(__y) == 0; }
620 
621  template<typename _CharT, typename _Traits>
622  [[nodiscard]]
623  constexpr auto
624  operator<=>(basic_string_view<_CharT, _Traits> __x,
625  __type_identity_t<basic_string_view<_CharT, _Traits>> __y)
626  noexcept
627  -> decltype(__detail::__char_traits_cmp_cat<_Traits>(0))
628  { return __detail::__char_traits_cmp_cat<_Traits>(__x.compare(__y)); }
629 #else
630  template<typename _CharT, typename _Traits>
631  [[nodiscard]]
632  constexpr bool
633  operator==(basic_string_view<_CharT, _Traits> __x,
634  __type_identity_t<basic_string_view<_CharT, _Traits>> __y)
635  noexcept
636  { return __x.size() == __y.size() && __x.compare(__y) == 0; }
637 
638  template<typename _CharT, typename _Traits>
639  [[nodiscard]]
640  constexpr bool
641  operator==(basic_string_view<_CharT, _Traits> __x,
642  basic_string_view<_CharT, _Traits> __y) noexcept
643  { return __x.size() == __y.size() && __x.compare(__y) == 0; }
644 
645  template<typename _CharT, typename _Traits>
646  [[nodiscard]]
647  constexpr bool
648  operator==(__type_identity_t<basic_string_view<_CharT, _Traits>> __x,
649  basic_string_view<_CharT, _Traits> __y) noexcept
650  { return __x.size() == __y.size() && __x.compare(__y) == 0; }
651 
652  template<typename _CharT, typename _Traits>
653  [[nodiscard]]
654  constexpr bool
655  operator!=(basic_string_view<_CharT, _Traits> __x,
656  basic_string_view<_CharT, _Traits> __y) noexcept
657  { return !(__x == __y); }
658 
659  template<typename _CharT, typename _Traits>
660  [[nodiscard]]
661  constexpr bool
662  operator!=(basic_string_view<_CharT, _Traits> __x,
663  __type_identity_t<basic_string_view<_CharT, _Traits>> __y)
664  noexcept
665  { return !(__x == __y); }
666 
667  template<typename _CharT, typename _Traits>
668  [[nodiscard]]
669  constexpr bool
670  operator!=(__type_identity_t<basic_string_view<_CharT, _Traits>> __x,
671  basic_string_view<_CharT, _Traits> __y) noexcept
672  { return !(__x == __y); }
673 
674  template<typename _CharT, typename _Traits>
675  [[nodiscard]]
676  constexpr bool
677  operator< (basic_string_view<_CharT, _Traits> __x,
678  basic_string_view<_CharT, _Traits> __y) noexcept
679  { return __x.compare(__y) < 0; }
680 
681  template<typename _CharT, typename _Traits>
682  [[nodiscard]]
683  constexpr bool
684  operator< (basic_string_view<_CharT, _Traits> __x,
685  __type_identity_t<basic_string_view<_CharT, _Traits>> __y)
686  noexcept
687  { return __x.compare(__y) < 0; }
688 
689  template<typename _CharT, typename _Traits>
690  [[nodiscard]]
691  constexpr bool
692  operator< (__type_identity_t<basic_string_view<_CharT, _Traits>> __x,
693  basic_string_view<_CharT, _Traits> __y) noexcept
694  { return __x.compare(__y) < 0; }
695 
696  template<typename _CharT, typename _Traits>
697  [[nodiscard]]
698  constexpr bool
699  operator> (basic_string_view<_CharT, _Traits> __x,
700  basic_string_view<_CharT, _Traits> __y) noexcept
701  { return __x.compare(__y) > 0; }
702 
703  template<typename _CharT, typename _Traits>
704  [[nodiscard]]
705  constexpr bool
706  operator> (basic_string_view<_CharT, _Traits> __x,
707  __type_identity_t<basic_string_view<_CharT, _Traits>> __y)
708  noexcept
709  { return __x.compare(__y) > 0; }
710 
711  template<typename _CharT, typename _Traits>
712  [[nodiscard]]
713  constexpr bool
714  operator> (__type_identity_t<basic_string_view<_CharT, _Traits>> __x,
715  basic_string_view<_CharT, _Traits> __y) noexcept
716  { return __x.compare(__y) > 0; }
717 
718  template<typename _CharT, typename _Traits>
719  [[nodiscard]]
720  constexpr bool
721  operator<=(basic_string_view<_CharT, _Traits> __x,
722  basic_string_view<_CharT, _Traits> __y) noexcept
723  { return __x.compare(__y) <= 0; }
724 
725  template<typename _CharT, typename _Traits>
726  [[nodiscard]]
727  constexpr bool
728  operator<=(basic_string_view<_CharT, _Traits> __x,
729  __type_identity_t<basic_string_view<_CharT, _Traits>> __y)
730  noexcept
731  { return __x.compare(__y) <= 0; }
732 
733  template<typename _CharT, typename _Traits>
734  [[nodiscard]]
735  constexpr bool
736  operator<=(__type_identity_t<basic_string_view<_CharT, _Traits>> __x,
737  basic_string_view<_CharT, _Traits> __y) noexcept
738  { return __x.compare(__y) <= 0; }
739 
740  template<typename _CharT, typename _Traits>
741  [[nodiscard]]
742  constexpr bool
743  operator>=(basic_string_view<_CharT, _Traits> __x,
744  basic_string_view<_CharT, _Traits> __y) noexcept
745  { return __x.compare(__y) >= 0; }
746 
747  template<typename _CharT, typename _Traits>
748  [[nodiscard]]
749  constexpr bool
750  operator>=(basic_string_view<_CharT, _Traits> __x,
751  __type_identity_t<basic_string_view<_CharT, _Traits>> __y)
752  noexcept
753  { return __x.compare(__y) >= 0; }
754 
755  template<typename _CharT, typename _Traits>
756  [[nodiscard]]
757  constexpr bool
758  operator>=(__type_identity_t<basic_string_view<_CharT, _Traits>> __x,
759  basic_string_view<_CharT, _Traits> __y) noexcept
760  { return __x.compare(__y) >= 0; }
761 #endif // three-way comparison
762 
763 #if _GLIBCXX_HOSTED
764  // [string.view.io], Inserters and extractors
765  template<typename _CharT, typename _Traits>
766  inline basic_ostream<_CharT, _Traits>&
767  operator<<(basic_ostream<_CharT, _Traits>& __os,
768  basic_string_view<_CharT,_Traits> __str)
769  { return __ostream_insert(__os, __str.data(), __str.size()); }
770 #endif // HOSTED
771 
772  // basic_string_view typedef names
773 
774  using string_view = basic_string_view<char>;
775  using wstring_view = basic_string_view<wchar_t>;
776 #ifdef _GLIBCXX_USE_CHAR8_T
777  using u8string_view = basic_string_view<char8_t>;
778 #endif
779  using u16string_view = basic_string_view<char16_t>;
780  using u32string_view = basic_string_view<char32_t>;
781 
782  // [string.view.hash], hash support:
783 
784  template<typename _Tp>
785  struct hash;
786 
787  template<>
788  struct hash<string_view>
789  : public __hash_base<size_t, string_view>
790  {
791  [[nodiscard]]
792  size_t
793  operator()(const string_view& __str) const noexcept
794  { return std::_Hash_impl::hash(__str.data(), __str.length()); }
795  };
796 
797  template<>
798  struct __is_fast_hash<hash<string_view>> : std::false_type
799  { };
800 
801  template<>
802  struct hash<wstring_view>
803  : public __hash_base<size_t, wstring_view>
804  {
805  [[nodiscard]]
806  size_t
807  operator()(const wstring_view& __s) const noexcept
808  { return std::_Hash_impl::hash(__s.data(),
809  __s.length() * sizeof(wchar_t)); }
810  };
811 
812  template<>
813  struct __is_fast_hash<hash<wstring_view>> : std::false_type
814  { };
815 
816 #ifdef _GLIBCXX_USE_CHAR8_T
817  template<>
818  struct hash<u8string_view>
819  : public __hash_base<size_t, u8string_view>
820  {
821  [[nodiscard]]
822  size_t
823  operator()(const u8string_view& __str) const noexcept
824  { return std::_Hash_impl::hash(__str.data(), __str.length()); }
825  };
826 
827  template<>
828  struct __is_fast_hash<hash<u8string_view>> : std::false_type
829  { };
830 #endif
831 
832  template<>
833  struct hash<u16string_view>
834  : public __hash_base<size_t, u16string_view>
835  {
836  [[nodiscard]]
837  size_t
838  operator()(const u16string_view& __s) const noexcept
839  { return std::_Hash_impl::hash(__s.data(),
840  __s.length() * sizeof(char16_t)); }
841  };
842 
843  template<>
844  struct __is_fast_hash<hash<u16string_view>> : std::false_type
845  { };
846 
847  template<>
848  struct hash<u32string_view>
849  : public __hash_base<size_t, u32string_view>
850  {
851  [[nodiscard]]
852  size_t
853  operator()(const u32string_view& __s) const noexcept
854  { return std::_Hash_impl::hash(__s.data(),
855  __s.length() * sizeof(char32_t)); }
856  };
857 
858  template<>
859  struct __is_fast_hash<hash<u32string_view>> : std::false_type
860  { };
861 
862  inline namespace literals
863  {
864  inline namespace string_view_literals
865  {
866 #pragma GCC diagnostic push
867 #pragma GCC diagnostic ignored "-Wliteral-suffix"
868  inline constexpr basic_string_view<char>
869  operator""sv(const char* __str, size_t __len) noexcept
870  { return basic_string_view<char>{__str, __len}; }
871 
872  inline constexpr basic_string_view<wchar_t>
873  operator""sv(const wchar_t* __str, size_t __len) noexcept
874  { return basic_string_view<wchar_t>{__str, __len}; }
875 
876 #ifdef _GLIBCXX_USE_CHAR8_T
877  inline constexpr basic_string_view<char8_t>
878  operator""sv(const char8_t* __str, size_t __len) noexcept
879  { return basic_string_view<char8_t>{__str, __len}; }
880 #endif
881 
882  inline constexpr basic_string_view<char16_t>
883  operator""sv(const char16_t* __str, size_t __len) noexcept
884  { return basic_string_view<char16_t>{__str, __len}; }
885 
886  inline constexpr basic_string_view<char32_t>
887  operator""sv(const char32_t* __str, size_t __len) noexcept
888  { return basic_string_view<char32_t>{__str, __len}; }
889 
890 #pragma GCC diagnostic pop
891  } // namespace string_literals
892  } // namespace literals
893 
894 #if __cpp_lib_concepts
895  namespace ranges
896  {
897  // Opt-in to borrowed_range concept
898  template<typename _CharT, typename _Traits>
899  inline constexpr bool
900  enable_borrowed_range<basic_string_view<_CharT, _Traits>> = true;
901 
902  // Opt-in to view concept
903  template<typename _CharT, typename _Traits>
904  inline constexpr bool
905  enable_view<basic_string_view<_CharT, _Traits>> = true;
906  }
907 #endif
908 _GLIBCXX_END_NAMESPACE_VERSION
909 } // namespace std
910 
911 #include <bits/string_view.tcc>
912 
913 #endif // __cplusplus <= 201402L
914 
915 #endif // _GLIBCXX_EXPERIMENTAL_STRING_VIEW