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