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