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