libstdc++: Only declare feature test macros in standard headers
[official-gcc.git] / libstdc++-v3 / include / std / string_view
blobcbb6bb0928fa9c79703c7b39402ce702d5f1c7d6
1 // Components for manipulating non-owning sequences of characters -*- C++ -*-
3 // Copyright (C) 2013-2023 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.
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.
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.
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/>.
25 /** @file include/string_view
26  *  This is a Standard C++ Library header.
27  */
30 // N3762 basic_string_view library
33 #ifndef _GLIBCXX_STRING_VIEW
34 #define _GLIBCXX_STRING_VIEW 1
36 #pragma GCC system_header
38 #define __glibcxx_want_constexpr_char_traits
39 #define __glibcxx_want_string_view
40 #define __glibcxx_want_constexpr_string_view
41 #define __glibcxx_want_starts_ends_with
42 #define __glibcxx_want_string_contains
43 #include <bits/version.h>
45 #if __cplusplus >= 201703L
47 #include <bits/char_traits.h>
48 #include <bits/functexcept.h>
49 #include <bits/functional_hash.h>
50 #include <bits/range_access.h>
51 #include <bits/stl_algobase.h>
52 #include <ext/numeric_traits.h>
54 #if __cplusplus >= 202002L
55 # include <bits/ranges_base.h>
56 #endif
58 #if _GLIBCXX_HOSTED
59 # include <iosfwd>
60 # include <bits/ostream_insert.h>
61 #endif
63 namespace std _GLIBCXX_VISIBILITY(default)
65 _GLIBCXX_BEGIN_NAMESPACE_VERSION
67   // Helper for basic_string and basic_string_view members.
68   constexpr size_t
69   __sv_check(size_t __size, size_t __pos, const char* __s)
70   {
71     if (__pos > __size)
72       __throw_out_of_range_fmt(__N("%s: __pos (which is %zu) > __size "
73                                    "(which is %zu)"), __s, __pos, __size);
74     return __pos;
75   }
77   // Helper for basic_string members.
78   // NB: __sv_limit doesn't check for a bad __pos value.
79   constexpr size_t
80   __sv_limit(size_t __size, size_t __pos, size_t __off) noexcept
81   {
82    const bool __testoff =  __off < __size - __pos;
83    return __testoff ? __off : __size - __pos;
84   }
86   /**
87    *  @class basic_string_view <string_view>
88    *  @brief  A non-owning reference to a string.
89    *
90    *  @ingroup strings
91    *  @ingroup sequences
92    *
93    *  @tparam _CharT  Type of character
94    *  @tparam _Traits  Traits for character type, defaults to
95    *                   char_traits<_CharT>.
96    *
97    *  A basic_string_view looks like this:
98    *
99    *  @code
100    *    _CharT*    _M_str
101    *    size_t     _M_len
102    *  @endcode
103    */
104   template<typename _CharT, typename _Traits = std::char_traits<_CharT>>
105     class basic_string_view
106     {
107       static_assert(!is_array_v<_CharT>);
108       static_assert(is_trivial_v<_CharT> && is_standard_layout_v<_CharT>);
109       static_assert(is_same_v<_CharT, typename _Traits::char_type>);
111     public:
113       // types
114       using traits_type         = _Traits;
115       using value_type          = _CharT;
116       using pointer             = value_type*;
117       using const_pointer       = const value_type*;
118       using reference           = value_type&;
119       using const_reference     = const value_type&;
120       using const_iterator      = const value_type*;
121       using iterator            = const_iterator;
122       using const_reverse_iterator = std::reverse_iterator<const_iterator>;
123       using reverse_iterator    = const_reverse_iterator;
124       using size_type           = size_t;
125       using difference_type     = ptrdiff_t;
126       static constexpr size_type npos = size_type(-1);
128       // [string.view.cons], construction and assignment
130       constexpr
131       basic_string_view() noexcept
132       : _M_len{0}, _M_str{nullptr}
133       { }
135       constexpr basic_string_view(const basic_string_view&) noexcept = default;
137       [[__gnu__::__nonnull__]]
138       constexpr
139       basic_string_view(const _CharT* __str) noexcept
140       : _M_len{traits_type::length(__str)},
141         _M_str{__str}
142       { }
144       constexpr
145       basic_string_view(const _CharT* __str, size_type __len) noexcept
146       : _M_len{__len}, _M_str{__str}
147       { }
149 #if __cplusplus >= 202002L && __cpp_lib_concepts
150       template<contiguous_iterator _It, sized_sentinel_for<_It> _End>
151         requires same_as<iter_value_t<_It>, _CharT>
152           && (!convertible_to<_End, size_type>)
153         constexpr
154         basic_string_view(_It __first, _End __last)
155         noexcept(noexcept(__last - __first))
156         : _M_len(__last - __first), _M_str(std::to_address(__first))
157         { }
159 #if __cplusplus > 202002L
160       template<typename _Range, typename _DRange = remove_cvref_t<_Range>>
161         requires (!is_same_v<_DRange, basic_string_view>)
162           && ranges::contiguous_range<_Range>
163           && ranges::sized_range<_Range>
164           && is_same_v<ranges::range_value_t<_Range>, _CharT>
165           && (!is_convertible_v<_Range, const _CharT*>)
166           && (!requires (_DRange& __d) {
167                 __d.operator ::std::basic_string_view<_CharT, _Traits>();
168               })
169           && (!requires { typename _DRange::traits_type; }
170               || is_same_v<typename _DRange::traits_type, _Traits>)
171         constexpr explicit
172         basic_string_view(_Range&& __r)
173         noexcept(noexcept(ranges::size(__r)) && noexcept(ranges::data(__r)))
174         : _M_len(ranges::size(__r)), _M_str(ranges::data(__r))
175         { }
177       basic_string_view(nullptr_t) = delete;
178 #endif // C++23
179 #endif // C++20
181       constexpr basic_string_view&
182       operator=(const basic_string_view&) noexcept = default;
184       // [string.view.iterators], iterator support
186       [[nodiscard]]
187       constexpr const_iterator
188       begin() const noexcept
189       { return this->_M_str; }
191       [[nodiscard]]
192       constexpr const_iterator
193       end() const noexcept
194       { return this->_M_str + this->_M_len; }
196       [[nodiscard]]
197       constexpr const_iterator
198       cbegin() const noexcept
199       { return this->_M_str; }
201       [[nodiscard]]
202       constexpr const_iterator
203       cend() const noexcept
204       { return this->_M_str + this->_M_len; }
206       [[nodiscard]]
207       constexpr const_reverse_iterator
208       rbegin() const noexcept
209       { return const_reverse_iterator(this->end()); }
211       [[nodiscard]]
212       constexpr const_reverse_iterator
213       rend() const noexcept
214       { return const_reverse_iterator(this->begin()); }
216       [[nodiscard]]
217       constexpr const_reverse_iterator
218       crbegin() const noexcept
219       { return const_reverse_iterator(this->end()); }
221       [[nodiscard]]
222       constexpr const_reverse_iterator
223       crend() const noexcept
224       { return const_reverse_iterator(this->begin()); }
226       // [string.view.capacity], capacity
228       [[nodiscard]]
229       constexpr size_type
230       size() const noexcept
231       { return this->_M_len; }
233       [[nodiscard]]
234       constexpr size_type
235       length() const noexcept
236       { return _M_len; }
238       [[nodiscard]]
239       constexpr size_type
240       max_size() const noexcept
241       {
242         return (npos - sizeof(size_type) - sizeof(void*))
243                 / sizeof(value_type) / 4;
244       }
246       [[nodiscard]]
247       constexpr bool
248       empty() const noexcept
249       { return this->_M_len == 0; }
251       // [string.view.access], element access
253       [[nodiscard]]
254       constexpr const_reference
255       operator[](size_type __pos) const noexcept
256       {
257         __glibcxx_assert(__pos < this->_M_len);
258         return *(this->_M_str + __pos);
259       }
261       [[nodiscard]]
262       constexpr const_reference
263       at(size_type __pos) const
264       {
265         if (__pos >= _M_len)
266           __throw_out_of_range_fmt(__N("basic_string_view::at: __pos "
267                                        "(which is %zu) >= this->size() "
268                                        "(which is %zu)"), __pos, this->size());
269         return *(this->_M_str + __pos);
270       }
272       [[nodiscard]]
273       constexpr const_reference
274       front() const noexcept
275       {
276         __glibcxx_assert(this->_M_len > 0);
277         return *this->_M_str;
278       }
280       [[nodiscard]]
281       constexpr const_reference
282       back() const noexcept
283       {
284         __glibcxx_assert(this->_M_len > 0);
285         return *(this->_M_str + this->_M_len - 1);
286       }
288       [[nodiscard]]
289       constexpr const_pointer
290       data() const noexcept
291       { return this->_M_str; }
293       // [string.view.modifiers], modifiers:
295       constexpr void
296       remove_prefix(size_type __n) noexcept
297       {
298         __glibcxx_assert(this->_M_len >= __n);
299         this->_M_str += __n;
300         this->_M_len -= __n;
301       }
303       constexpr void
304       remove_suffix(size_type __n) noexcept
305       {
306         __glibcxx_assert(this->_M_len >= __n);
307         this->_M_len -= __n;
308       }
310       constexpr void
311       swap(basic_string_view& __sv) noexcept
312       {
313         auto __tmp = *this;
314         *this = __sv;
315         __sv = __tmp;
316       }
318       // [string.view.ops], string operations:
320       _GLIBCXX20_CONSTEXPR
321       size_type
322       copy(_CharT* __str, size_type __n, size_type __pos = 0) const
323       {
324         __glibcxx_requires_string_len(__str, __n);
325         __pos = std::__sv_check(size(), __pos, "basic_string_view::copy");
326         const size_type __rlen = std::min<size_t>(__n, _M_len - __pos);
327         // _GLIBCXX_RESOLVE_LIB_DEFECTS
328         // 2777. basic_string_view::copy should use char_traits::copy
329         traits_type::copy(__str, data() + __pos, __rlen);
330         return __rlen;
331       }
333       [[nodiscard]]
334       constexpr basic_string_view
335       substr(size_type __pos = 0, size_type __n = npos) const noexcept(false)
336       {
337         __pos = std::__sv_check(size(), __pos, "basic_string_view::substr");
338         const size_type __rlen = std::min<size_t>(__n, _M_len - __pos);
339         return basic_string_view{_M_str + __pos, __rlen};
340       }
342       [[nodiscard]]
343       constexpr int
344       compare(basic_string_view __str) const noexcept
345       {
346         const size_type __rlen = std::min(this->_M_len, __str._M_len);
347         int __ret = traits_type::compare(this->_M_str, __str._M_str, __rlen);
348         if (__ret == 0)
349           __ret = _S_compare(this->_M_len, __str._M_len);
350         return __ret;
351       }
353       [[nodiscard]]
354       constexpr int
355       compare(size_type __pos1, size_type __n1, basic_string_view __str) const
356       { return this->substr(__pos1, __n1).compare(__str); }
358       [[nodiscard]]
359       constexpr int
360       compare(size_type __pos1, size_type __n1,
361               basic_string_view __str, size_type __pos2, size_type __n2) const
362       {
363         return this->substr(__pos1, __n1).compare(__str.substr(__pos2, __n2));
364       }
366       [[nodiscard, __gnu__::__nonnull__]]
367       constexpr int
368       compare(const _CharT* __str) const noexcept
369       { return this->compare(basic_string_view{__str}); }
371       [[nodiscard, __gnu__::__nonnull__]]
372       constexpr int
373       compare(size_type __pos1, size_type __n1, const _CharT* __str) const
374       { return this->substr(__pos1, __n1).compare(basic_string_view{__str}); }
376       [[nodiscard]]
377       constexpr int
378       compare(size_type __pos1, size_type __n1,
379               const _CharT* __str, size_type __n2) const noexcept(false)
380       {
381         return this->substr(__pos1, __n1)
382                    .compare(basic_string_view(__str, __n2));
383       }
385 #ifdef __cpp_lib_starts_ends_with // C++ >= 20
386       [[nodiscard]]
387       constexpr bool
388       starts_with(basic_string_view __x) const noexcept
389       { return this->substr(0, __x.size()) == __x; }
391       [[nodiscard]]
392       constexpr bool
393       starts_with(_CharT __x) const noexcept
394       { return !this->empty() && traits_type::eq(this->front(), __x); }
396       [[nodiscard, __gnu__::__nonnull__]]
397       constexpr bool
398       starts_with(const _CharT* __x) const noexcept
399       { return this->starts_with(basic_string_view(__x)); }
401       [[nodiscard]]
402       constexpr bool
403       ends_with(basic_string_view __x) const noexcept
404       {
405         const auto __len = this->size();
406         const auto __xlen = __x.size();
407         return __len >= __xlen
408           && traits_type::compare(end() - __xlen, __x.data(), __xlen) == 0;
409       }
411       [[nodiscard]]
412       constexpr bool
413       ends_with(_CharT __x) const noexcept
414       { return !this->empty() && traits_type::eq(this->back(), __x); }
416       [[nodiscard, __gnu__::__nonnull__]]
417       constexpr bool
418       ends_with(const _CharT* __x) const noexcept
419       { return this->ends_with(basic_string_view(__x)); }
420 #endif // __cpp_lib_starts_ends_with
422 #if __cplusplus > 202002L
423 #if _GLIBCXX_HOSTED && !defined(__cpp_lib_string_contains)
424       // This FTM is not freestanding as it also implies matching <string>
425       // support, and <string> is omitted from the freestanding subset.
426 # error "libstdc++ bug: string_contains not defined when it should be"
427 #endif // HOSTED
428       [[nodiscard]]
429       constexpr bool
430       contains(basic_string_view __x) const noexcept
431       { return this->find(__x) != npos; }
433       [[nodiscard]]
434       constexpr bool
435       contains(_CharT __x) const noexcept
436       { return this->find(__x) != npos; }
438       [[nodiscard, __gnu__::__nonnull__]]
439       constexpr bool
440       contains(const _CharT* __x) const noexcept
441       { return this->find(__x) != npos; }
442 #endif // C++23
444       // [string.view.find], searching
446       [[nodiscard]]
447       constexpr size_type
448       find(basic_string_view __str, size_type __pos = 0) const noexcept
449       { return this->find(__str._M_str, __pos, __str._M_len); }
451       [[nodiscard]]
452       constexpr size_type
453       find(_CharT __c, size_type __pos = 0) const noexcept;
455       [[nodiscard]]
456       constexpr size_type
457       find(const _CharT* __str, size_type __pos, size_type __n) const noexcept;
459       [[nodiscard, __gnu__::__nonnull__]]
460       constexpr size_type
461       find(const _CharT* __str, size_type __pos = 0) const noexcept
462       { return this->find(__str, __pos, traits_type::length(__str)); }
464       [[nodiscard]]
465       constexpr size_type
466       rfind(basic_string_view __str, size_type __pos = npos) const noexcept
467       { return this->rfind(__str._M_str, __pos, __str._M_len); }
469       [[nodiscard]]
470       constexpr size_type
471       rfind(_CharT __c, size_type __pos = npos) const noexcept;
473       [[nodiscard]]
474       constexpr size_type
475       rfind(const _CharT* __str, size_type __pos, size_type __n) const noexcept;
477       [[nodiscard, __gnu__::__nonnull__]]
478       constexpr size_type
479       rfind(const _CharT* __str, size_type __pos = npos) const noexcept
480       { return this->rfind(__str, __pos, traits_type::length(__str)); }
482       [[nodiscard]]
483       constexpr size_type
484       find_first_of(basic_string_view __str, size_type __pos = 0) const noexcept
485       { return this->find_first_of(__str._M_str, __pos, __str._M_len); }
487       [[nodiscard]]
488       constexpr size_type
489       find_first_of(_CharT __c, size_type __pos = 0) const noexcept
490       { return this->find(__c, __pos); }
492       [[nodiscard]]
493       constexpr size_type
494       find_first_of(const _CharT* __str, size_type __pos,
495                     size_type __n) const noexcept;
497       [[nodiscard, __gnu__::__nonnull__]]
498       constexpr size_type
499       find_first_of(const _CharT* __str, size_type __pos = 0) const noexcept
500       { return this->find_first_of(__str, __pos, traits_type::length(__str)); }
502       [[nodiscard]]
503       constexpr size_type
504       find_last_of(basic_string_view __str,
505                    size_type __pos = npos) const noexcept
506       { return this->find_last_of(__str._M_str, __pos, __str._M_len); }
508       [[nodiscard]]
509       constexpr size_type
510       find_last_of(_CharT __c, size_type __pos=npos) const noexcept
511       { return this->rfind(__c, __pos); }
513       [[nodiscard]]
514       constexpr size_type
515       find_last_of(const _CharT* __str, size_type __pos,
516                    size_type __n) const noexcept;
518       [[nodiscard, __gnu__::__nonnull__]]
519       constexpr size_type
520       find_last_of(const _CharT* __str, size_type __pos = npos) const noexcept
521       { return this->find_last_of(__str, __pos, traits_type::length(__str)); }
523       [[nodiscard]]
524       constexpr size_type
525       find_first_not_of(basic_string_view __str,
526                         size_type __pos = 0) const noexcept
527       { return this->find_first_not_of(__str._M_str, __pos, __str._M_len); }
529       [[nodiscard]]
530       constexpr size_type
531       find_first_not_of(_CharT __c, size_type __pos = 0) const noexcept;
533       [[nodiscard]]
534       constexpr size_type
535       find_first_not_of(const _CharT* __str,
536                         size_type __pos, size_type __n) const noexcept;
538       [[nodiscard, __gnu__::__nonnull__]]
539       constexpr size_type
540       find_first_not_of(const _CharT* __str, size_type __pos = 0) const noexcept
541       {
542         return this->find_first_not_of(__str, __pos,
543                                        traits_type::length(__str));
544       }
546       [[nodiscard]]
547       constexpr size_type
548       find_last_not_of(basic_string_view __str,
549                        size_type __pos = npos) const noexcept
550       { return this->find_last_not_of(__str._M_str, __pos, __str._M_len); }
552       [[nodiscard]]
553       constexpr size_type
554       find_last_not_of(_CharT __c, size_type __pos = npos) const noexcept;
556       [[nodiscard]]
557       constexpr size_type
558       find_last_not_of(const _CharT* __str,
559                        size_type __pos, size_type __n) const noexcept;
561       [[nodiscard, __gnu__::__nonnull__]]
562       constexpr size_type
563       find_last_not_of(const _CharT* __str,
564                        size_type __pos = npos) const noexcept
565       {
566         return this->find_last_not_of(__str, __pos,
567                                       traits_type::length(__str));
568       }
570     private:
572       static constexpr int
573       _S_compare(size_type __n1, size_type __n2) noexcept
574       {
575         using __limits = __gnu_cxx::__int_traits<int>;
576         const difference_type __diff = __n1 - __n2;
577         if (__diff > __limits::__max)
578           return __limits::__max;
579         if (__diff < __limits::__min)
580           return __limits::__min;
581         return static_cast<int>(__diff);
582       }
584       size_t        _M_len;
585       const _CharT* _M_str;
586     };
588 #if __cplusplus > 201703L && __cpp_lib_concepts && __cpp_deduction_guides
589   template<contiguous_iterator _It, sized_sentinel_for<_It> _End>
590     basic_string_view(_It, _End) -> basic_string_view<iter_value_t<_It>>;
592 #if __cplusplus > 202002L
593   template<ranges::contiguous_range _Range>
594     basic_string_view(_Range&&)
595       -> basic_string_view<ranges::range_value_t<_Range>>;
596 #endif
597 #endif
599   // [string.view.comparison], non-member basic_string_view comparison function
601   // Several of these functions use type_identity_t to create a non-deduced
602   // context, so that only one argument participates in template argument
603   // deduction and the other argument gets implicitly converted to the deduced
604   // type (see N3766).
606   template<typename _CharT, typename _Traits>
607     [[nodiscard]]
608     constexpr bool
609     operator==(basic_string_view<_CharT, _Traits> __x,
610                __type_identity_t<basic_string_view<_CharT, _Traits>> __y)
611     noexcept
612     { return __x.size() == __y.size() && __x.compare(__y) == 0; }
614 #if __cpp_lib_three_way_comparison
615   template<typename _CharT, typename _Traits>
616     [[nodiscard]]
617     constexpr auto
618     operator<=>(basic_string_view<_CharT, _Traits> __x,
619                 __type_identity_t<basic_string_view<_CharT, _Traits>> __y)
620     noexcept
621     -> decltype(__detail::__char_traits_cmp_cat<_Traits>(0))
622     { return __detail::__char_traits_cmp_cat<_Traits>(__x.compare(__y)); }
623 #else
624   template<typename _CharT, typename _Traits>
625     [[nodiscard]]
626     constexpr bool
627     operator==(basic_string_view<_CharT, _Traits> __x,
628                basic_string_view<_CharT, _Traits> __y) noexcept
629     { return __x.size() == __y.size() && __x.compare(__y) == 0; }
631   template<typename _CharT, typename _Traits>
632     [[nodiscard]]
633     constexpr bool
634     operator==(__type_identity_t<basic_string_view<_CharT, _Traits>> __x,
635                basic_string_view<_CharT, _Traits> __y) noexcept
636     { return __x.size() == __y.size() && __x.compare(__y) == 0; }
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 == __y); }
645   template<typename _CharT, typename _Traits>
646     [[nodiscard]]
647     constexpr bool
648     operator!=(basic_string_view<_CharT, _Traits> __x,
649                __type_identity_t<basic_string_view<_CharT, _Traits>> __y)
650     noexcept
651     { return !(__x == __y); }
653   template<typename _CharT, typename _Traits>
654     [[nodiscard]]
655     constexpr bool
656     operator!=(__type_identity_t<basic_string_view<_CharT, _Traits>> __x,
657                basic_string_view<_CharT, _Traits> __y) noexcept
658     { return !(__x == __y); }
660   template<typename _CharT, typename _Traits>
661     [[nodiscard]]
662     constexpr bool
663     operator< (basic_string_view<_CharT, _Traits> __x,
664                basic_string_view<_CharT, _Traits> __y) noexcept
665     { return __x.compare(__y) < 0; }
667   template<typename _CharT, typename _Traits>
668     [[nodiscard]]
669     constexpr bool
670     operator< (basic_string_view<_CharT, _Traits> __x,
671                __type_identity_t<basic_string_view<_CharT, _Traits>> __y)
672     noexcept
673     { return __x.compare(__y) < 0; }
675   template<typename _CharT, typename _Traits>
676     [[nodiscard]]
677     constexpr bool
678     operator< (__type_identity_t<basic_string_view<_CharT, _Traits>> __x,
679                basic_string_view<_CharT, _Traits> __y) noexcept
680     { return __x.compare(__y) < 0; }
682   template<typename _CharT, typename _Traits>
683     [[nodiscard]]
684     constexpr bool
685     operator> (basic_string_view<_CharT, _Traits> __x,
686                basic_string_view<_CharT, _Traits> __y) noexcept
687     { return __x.compare(__y) > 0; }
689   template<typename _CharT, typename _Traits>
690     [[nodiscard]]
691     constexpr bool
692     operator> (basic_string_view<_CharT, _Traits> __x,
693                __type_identity_t<basic_string_view<_CharT, _Traits>> __y)
694     noexcept
695     { return __x.compare(__y) > 0; }
697   template<typename _CharT, typename _Traits>
698     [[nodiscard]]
699     constexpr bool
700     operator> (__type_identity_t<basic_string_view<_CharT, _Traits>> __x,
701                basic_string_view<_CharT, _Traits> __y) noexcept
702     { return __x.compare(__y) > 0; }
704   template<typename _CharT, typename _Traits>
705     [[nodiscard]]
706     constexpr bool
707     operator<=(basic_string_view<_CharT, _Traits> __x,
708                basic_string_view<_CharT, _Traits> __y) noexcept
709     { return __x.compare(__y) <= 0; }
711   template<typename _CharT, typename _Traits>
712     [[nodiscard]]
713     constexpr bool
714     operator<=(basic_string_view<_CharT, _Traits> __x,
715                __type_identity_t<basic_string_view<_CharT, _Traits>> __y)
716     noexcept
717     { return __x.compare(__y) <= 0; }
719   template<typename _CharT, typename _Traits>
720     [[nodiscard]]
721     constexpr bool
722     operator<=(__type_identity_t<basic_string_view<_CharT, _Traits>> __x,
723                basic_string_view<_CharT, _Traits> __y) noexcept
724     { return __x.compare(__y) <= 0; }
726   template<typename _CharT, typename _Traits>
727     [[nodiscard]]
728     constexpr bool
729     operator>=(basic_string_view<_CharT, _Traits> __x,
730                basic_string_view<_CharT, _Traits> __y) noexcept
731     { return __x.compare(__y) >= 0; }
733   template<typename _CharT, typename _Traits>
734     [[nodiscard]]
735     constexpr bool
736     operator>=(basic_string_view<_CharT, _Traits> __x,
737                __type_identity_t<basic_string_view<_CharT, _Traits>> __y)
738     noexcept
739     { return __x.compare(__y) >= 0; }
741   template<typename _CharT, typename _Traits>
742     [[nodiscard]]
743     constexpr bool
744     operator>=(__type_identity_t<basic_string_view<_CharT, _Traits>> __x,
745                basic_string_view<_CharT, _Traits> __y) noexcept
746     { return __x.compare(__y) >= 0; }
747 #endif // three-way comparison
749 #if _GLIBCXX_HOSTED
750   // [string.view.io], Inserters and extractors
751   template<typename _CharT, typename _Traits>
752     inline basic_ostream<_CharT, _Traits>&
753     operator<<(basic_ostream<_CharT, _Traits>& __os,
754                basic_string_view<_CharT,_Traits> __str)
755     { return __ostream_insert(__os, __str.data(), __str.size()); }
756 #endif // HOSTED
758   // basic_string_view typedef names
760   using string_view = basic_string_view<char>;
761   using wstring_view = basic_string_view<wchar_t>;
762 #ifdef _GLIBCXX_USE_CHAR8_T
763   using u8string_view = basic_string_view<char8_t>;
764 #endif
765   using u16string_view = basic_string_view<char16_t>;
766   using u32string_view = basic_string_view<char32_t>;
768   // [string.view.hash], hash support:
770   template<typename _Tp>
771     struct hash;
773   template<>
774     struct hash<string_view>
775     : public __hash_base<size_t, string_view>
776     {
777       [[nodiscard]]
778       size_t
779       operator()(const string_view& __str) const noexcept
780       { return std::_Hash_impl::hash(__str.data(), __str.length()); }
781     };
783   template<>
784     struct __is_fast_hash<hash<string_view>> : std::false_type
785     { };
787   template<>
788     struct hash<wstring_view>
789     : public __hash_base<size_t, wstring_view>
790     {
791       [[nodiscard]]
792       size_t
793       operator()(const wstring_view& __s) const noexcept
794       { return std::_Hash_impl::hash(__s.data(),
795                                      __s.length() * sizeof(wchar_t)); }
796     };
798   template<>
799     struct __is_fast_hash<hash<wstring_view>> : std::false_type
800     { };
802 #ifdef _GLIBCXX_USE_CHAR8_T
803   template<>
804     struct hash<u8string_view>
805     : public __hash_base<size_t, u8string_view>
806     {
807       [[nodiscard]]
808       size_t
809       operator()(const u8string_view& __str) const noexcept
810       { return std::_Hash_impl::hash(__str.data(), __str.length()); }
811     };
813   template<>
814     struct __is_fast_hash<hash<u8string_view>> : std::false_type
815     { };
816 #endif
818   template<>
819     struct hash<u16string_view>
820     : public __hash_base<size_t, u16string_view>
821     {
822       [[nodiscard]]
823       size_t
824       operator()(const u16string_view& __s) const noexcept
825       { return std::_Hash_impl::hash(__s.data(),
826                                      __s.length() * sizeof(char16_t)); }
827     };
829   template<>
830     struct __is_fast_hash<hash<u16string_view>> : std::false_type
831     { };
833   template<>
834     struct hash<u32string_view>
835     : public __hash_base<size_t, u32string_view>
836     {
837       [[nodiscard]]
838       size_t
839       operator()(const u32string_view& __s) const noexcept
840       { return std::_Hash_impl::hash(__s.data(),
841                                      __s.length() * sizeof(char32_t)); }
842     };
844   template<>
845     struct __is_fast_hash<hash<u32string_view>> : std::false_type
846     { };
848   inline namespace literals
849   {
850   inline namespace string_view_literals
851   {
852 #pragma GCC diagnostic push
853 #pragma GCC diagnostic ignored "-Wliteral-suffix"
854     inline constexpr basic_string_view<char>
855     operator""sv(const char* __str, size_t __len) noexcept
856     { return basic_string_view<char>{__str, __len}; }
858     inline constexpr basic_string_view<wchar_t>
859     operator""sv(const wchar_t* __str, size_t __len) noexcept
860     { return basic_string_view<wchar_t>{__str, __len}; }
862 #ifdef _GLIBCXX_USE_CHAR8_T
863     inline constexpr basic_string_view<char8_t>
864     operator""sv(const char8_t* __str, size_t __len) noexcept
865     { return basic_string_view<char8_t>{__str, __len}; }
866 #endif
868     inline constexpr basic_string_view<char16_t>
869     operator""sv(const char16_t* __str, size_t __len) noexcept
870     { return basic_string_view<char16_t>{__str, __len}; }
872     inline constexpr basic_string_view<char32_t>
873     operator""sv(const char32_t* __str, size_t __len) noexcept
874     { return basic_string_view<char32_t>{__str, __len}; }
876 #pragma GCC diagnostic pop
877   } // namespace string_literals
878   } // namespace literals
880 #if __cpp_lib_concepts
881   namespace ranges
882   {
883     // Opt-in to borrowed_range concept
884     template<typename _CharT, typename _Traits>
885       inline constexpr bool
886         enable_borrowed_range<basic_string_view<_CharT, _Traits>> = true;
888     // Opt-in to view concept
889     template<typename _CharT, typename _Traits>
890       inline constexpr bool
891         enable_view<basic_string_view<_CharT, _Traits>> = true;
892   }
893 #endif
894 _GLIBCXX_END_NAMESPACE_VERSION
895 } // namespace std
897 #include <bits/string_view.tcc>
899 #endif // __cplusplus <= 201402L
901 #endif // _GLIBCXX_EXPERIMENTAL_STRING_VIEW