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