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