Home | History | Annotate | Line # | Download | only in experimental
      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 experimental/string_view
     26  *  This is a TS C++ Library header.
     27  *  @ingroup libfund-ts
     28  */
     29 
     30 //
     31 // N3762 basic_string_view library
     32 //
     33 
     34 #ifndef _GLIBCXX_EXPERIMENTAL_STRING_VIEW
     35 #define _GLIBCXX_EXPERIMENTAL_STRING_VIEW 1
     36 
     37 #pragma GCC system_header
     38 
     39 #if __cplusplus >= 201402L
     40 
     41 #include <string>
     42 #include <limits>
     43 #include <bits/ranges_base.h> // enable_borrowed_range, enable_view
     44 #include <experimental/bits/lfts_config.h>
     45 
     46 namespace std _GLIBCXX_VISIBILITY(default)
     47 {
     48 _GLIBCXX_BEGIN_NAMESPACE_VERSION
     49 
     50 namespace experimental
     51 {
     52 inline namespace fundamentals_v1
     53 {
     54 #define __cpp_lib_experimental_string_view 201411
     55 
     56   /**
     57    *  @class basic_string_view <experimental/string_view>
     58    *  @brief  A non-owning reference to a string.
     59    *
     60    *  @ingroup strings
     61    *  @ingroup sequences
     62    *  @ingroup libfund-ts
     63    *
     64    *  @tparam _CharT  Type of character
     65    *  @tparam _Traits  Traits for character type, defaults to
     66    *                   char_traits<_CharT>.
     67    *
     68    *  A basic_string_view looks like this:
     69    *
     70    *  @code
     71    *    _CharT*    _M_str
     72    *    size_t     _M_len
     73    *  @endcode
     74    */
     75   template<typename _CharT, typename _Traits = std::char_traits<_CharT>>
     76     class basic_string_view
     77     {
     78     public:
     79 
     80       // types
     81       using traits_type = _Traits;
     82       using value_type = _CharT;
     83       using pointer = _CharT*;
     84       using const_pointer = const _CharT*;
     85       using reference = _CharT&;
     86       using const_reference = const _CharT&;
     87       using const_iterator = const _CharT*;
     88       using iterator = const_iterator;
     89       using const_reverse_iterator = std::reverse_iterator<const_iterator>;
     90       using reverse_iterator = const_reverse_iterator;
     91       using size_type = size_t;
     92       using difference_type = ptrdiff_t;
     93       static constexpr size_type npos = size_type(-1);
     94 
     95       // [string.view.cons], construct/copy
     96 
     97       constexpr
     98       basic_string_view() noexcept
     99       : _M_len{0}, _M_str{nullptr}
    100       { }
    101 
    102       constexpr basic_string_view(const basic_string_view&) noexcept = default;
    103 
    104       template<typename _Allocator>
    105         basic_string_view(const basic_string<_CharT, _Traits,
    106 			  _Allocator>& __str) noexcept
    107         : _M_len{__str.length()}, _M_str{__str.data()}
    108         { }
    109 
    110       constexpr basic_string_view(const _CharT* __str)
    111       : _M_len{__str == nullptr ? 0 : traits_type::length(__str)},
    112 	_M_str{__str}
    113       { }
    114 
    115       constexpr basic_string_view(const _CharT* __str, size_type __len)
    116       : _M_len{__len},
    117         _M_str{__str}
    118       { }
    119 
    120       basic_string_view&
    121       operator=(const basic_string_view&) noexcept = default;
    122 
    123       // [string.view.iterators], iterators
    124 
    125       constexpr const_iterator
    126       begin() const noexcept
    127       { return this->_M_str; }
    128 
    129       constexpr const_iterator
    130       end() const noexcept
    131       { return this->_M_str + this->_M_len; }
    132 
    133       constexpr const_iterator
    134       cbegin() const noexcept
    135       { return this->_M_str; }
    136 
    137       constexpr const_iterator
    138       cend() const noexcept
    139       { return this->_M_str + this->_M_len; }
    140 
    141       const_reverse_iterator
    142       rbegin() const noexcept
    143       { return const_reverse_iterator(this->end()); }
    144 
    145       const_reverse_iterator
    146       rend() const noexcept
    147       { return const_reverse_iterator(this->begin()); }
    148 
    149       const_reverse_iterator
    150       crbegin() const noexcept
    151       { return const_reverse_iterator(this->end()); }
    152 
    153       const_reverse_iterator
    154       crend() const noexcept
    155       { return const_reverse_iterator(this->begin()); }
    156 
    157       // [string.view.capacity], capacity
    158 
    159       constexpr size_type
    160       size() const noexcept
    161       { return this->_M_len; }
    162 
    163       constexpr size_type
    164       length() const noexcept
    165       { return _M_len; }
    166 
    167       constexpr size_type
    168       max_size() const noexcept
    169       {
    170 	return (npos - sizeof(size_type) - sizeof(void*))
    171 		/ sizeof(value_type) / 4;
    172       }
    173 
    174       _GLIBCXX_NODISCARD constexpr bool
    175       empty() const noexcept
    176       { return this->_M_len == 0; }
    177 
    178       // [string.view.access], element access
    179 
    180       constexpr const _CharT&
    181       operator[](size_type __pos) const
    182       {
    183 	__glibcxx_assert(__pos < this->_M_len);
    184 	return *(this->_M_str + __pos);
    185       }
    186 
    187       constexpr const _CharT&
    188       at(size_type __pos) const
    189       {
    190 	return __pos < this->_M_len
    191 	     ? *(this->_M_str + __pos)
    192 	     : (__throw_out_of_range_fmt(__N("basic_string_view::at: __pos "
    193 					     "(which is %zu) >= this->size() "
    194 					     "(which is %zu)"),
    195 					 __pos, this->size()),
    196 		*this->_M_str);
    197       }
    198 
    199       constexpr const _CharT&
    200       front() const
    201       {
    202 	__glibcxx_assert(this->_M_len > 0);
    203 	return *this->_M_str;
    204       }
    205 
    206       constexpr const _CharT&
    207       back() const
    208       {
    209 	__glibcxx_assert(this->_M_len > 0);
    210 	return *(this->_M_str + this->_M_len - 1);
    211       }
    212 
    213       constexpr const _CharT*
    214       data() const noexcept
    215       { return this->_M_str; }
    216 
    217       // [string.view.modifiers], modifiers:
    218 
    219       constexpr void
    220       remove_prefix(size_type __n)
    221       {
    222 	__glibcxx_assert(this->_M_len >= __n);
    223 	this->_M_str += __n;
    224 	this->_M_len -= __n;
    225       }
    226 
    227       constexpr void
    228       remove_suffix(size_type __n)
    229       { this->_M_len -= __n; }
    230 
    231       constexpr void
    232       swap(basic_string_view& __sv) noexcept
    233       {
    234 	auto __tmp = *this;
    235 	*this = __sv;
    236 	__sv = __tmp;
    237       }
    238 
    239 
    240       // [string.view.ops], string operations:
    241 
    242       template<typename _Allocator>
    243         explicit operator basic_string<_CharT, _Traits, _Allocator>() const
    244         {
    245 	  return { this->_M_str, this->_M_len };
    246 	}
    247 
    248       template<typename _Allocator = std::allocator<_CharT>>
    249 	basic_string<_CharT, _Traits, _Allocator>
    250 	to_string(const _Allocator& __alloc = _Allocator()) const
    251 	{
    252 	  return { this->_M_str, this->_M_len, __alloc };
    253 	}
    254 
    255       size_type
    256       copy(_CharT* __str, size_type __n, size_type __pos = 0) const
    257       {
    258 	__glibcxx_requires_string_len(__str, __n);
    259 	if (__pos > this->_M_len)
    260 	  __throw_out_of_range_fmt(__N("basic_string_view::copy: __pos "
    261 				       "(which is %zu) > this->size() "
    262 				       "(which is %zu)"),
    263 				   __pos, this->size());
    264 	size_type __rlen{std::min(__n, size_type{this->_M_len  - __pos})};
    265 	for (auto __begin = this->_M_str + __pos,
    266 	     __end = __begin + __rlen; __begin != __end;)
    267 	  *__str++ = *__begin++;
    268 	return __rlen;
    269       }
    270 
    271 
    272       // [string.view.ops], string operations:
    273 
    274       constexpr basic_string_view
    275       substr(size_type __pos = 0, size_type __n = npos) const
    276       {
    277 	return __pos <= this->_M_len
    278 	     ? basic_string_view{this->_M_str + __pos,
    279 				std::min(__n, size_type{this->_M_len  - __pos})}
    280 	     : (__throw_out_of_range_fmt(__N("basic_string_view::substr: __pos "
    281 					     "(which is %zu) > this->size() "
    282 					     "(which is %zu)"),
    283 				     __pos, this->size()), basic_string_view{});
    284       }
    285 
    286       constexpr int
    287       compare(basic_string_view __str) const noexcept
    288       {
    289 	int __ret = traits_type::compare(this->_M_str, __str._M_str,
    290 					 std::min(this->_M_len, __str._M_len));
    291 	if (__ret == 0)
    292 	  __ret = _S_compare(this->_M_len, __str._M_len);
    293 	return __ret;
    294       }
    295 
    296       constexpr int
    297       compare(size_type __pos1, size_type __n1, basic_string_view __str) const
    298       { return this->substr(__pos1, __n1).compare(__str); }
    299 
    300       constexpr int
    301       compare(size_type __pos1, size_type __n1,
    302 	      basic_string_view __str, size_type __pos2, size_type __n2) const
    303       { return this->substr(__pos1, __n1).compare(__str.substr(__pos2, __n2)); }
    304 
    305       constexpr int
    306       compare(const _CharT* __str) const noexcept
    307       { return this->compare(basic_string_view{__str}); }
    308 
    309       constexpr int
    310       compare(size_type __pos1, size_type __n1, const _CharT* __str) const
    311       { return this->substr(__pos1, __n1).compare(basic_string_view{__str}); }
    312 
    313       constexpr int
    314       compare(size_type __pos1, size_type __n1,
    315 	      const _CharT* __str, size_type __n2) const
    316       {
    317 	return this->substr(__pos1, __n1)
    318 		   .compare(basic_string_view(__str, __n2));
    319       }
    320 
    321       constexpr size_type
    322       find(basic_string_view __str, size_type __pos = 0) const noexcept
    323       { return this->find(__str._M_str, __pos, __str._M_len); }
    324 
    325       constexpr size_type
    326       find(_CharT __c, size_type __pos=0) const noexcept;
    327 
    328       constexpr size_type
    329       find(const _CharT* __str, size_type __pos, size_type __n) const noexcept;
    330 
    331       constexpr size_type
    332       find(const _CharT* __str, size_type __pos=0) const noexcept
    333       { return this->find(__str, __pos, traits_type::length(__str)); }
    334 
    335       constexpr size_type
    336       rfind(basic_string_view __str, size_type __pos = npos) const noexcept
    337       { return this->rfind(__str._M_str, __pos, __str._M_len); }
    338 
    339       constexpr size_type
    340       rfind(_CharT __c, size_type __pos = npos) const noexcept;
    341 
    342       constexpr size_type
    343       rfind(const _CharT* __str, size_type __pos, size_type __n) const noexcept;
    344 
    345       constexpr size_type
    346       rfind(const _CharT* __str, size_type __pos = npos) const noexcept
    347       { return this->rfind(__str, __pos, traits_type::length(__str)); }
    348 
    349       constexpr size_type
    350       find_first_of(basic_string_view __str, size_type __pos = 0) const noexcept
    351       { return this->find_first_of(__str._M_str, __pos, __str._M_len); }
    352 
    353       constexpr size_type
    354       find_first_of(_CharT __c, size_type __pos = 0) const noexcept
    355       { return this->find(__c, __pos); }
    356 
    357       constexpr size_type
    358       find_first_of(const _CharT* __str, size_type __pos, size_type __n) const;
    359 
    360       constexpr size_type
    361       find_first_of(const _CharT* __str, size_type __pos = 0) const noexcept
    362       { return this->find_first_of(__str, __pos, traits_type::length(__str)); }
    363 
    364       constexpr size_type
    365       find_last_of(basic_string_view __str,
    366 		   size_type __pos = npos) const noexcept
    367       { return this->find_last_of(__str._M_str, __pos, __str._M_len); }
    368 
    369       constexpr size_type
    370       find_last_of(_CharT __c, size_type __pos=npos) const noexcept
    371       { return this->rfind(__c, __pos); }
    372 
    373       constexpr size_type
    374       find_last_of(const _CharT* __str, size_type __pos, size_type __n) const;
    375 
    376       constexpr size_type
    377       find_last_of(const _CharT* __str, size_type __pos = npos) const noexcept
    378       { return this->find_last_of(__str, __pos, traits_type::length(__str)); }
    379 
    380       constexpr size_type
    381       find_first_not_of(basic_string_view __str,
    382 			size_type __pos = 0) const noexcept
    383       { return this->find_first_not_of(__str._M_str, __pos, __str._M_len); }
    384 
    385       constexpr size_type
    386       find_first_not_of(_CharT __c, size_type __pos = 0) const noexcept;
    387 
    388       constexpr size_type
    389       find_first_not_of(const _CharT* __str,
    390 			size_type __pos, size_type __n) const;
    391 
    392       constexpr size_type
    393       find_first_not_of(const _CharT* __str, size_type __pos = 0) const noexcept
    394       {
    395 	return this->find_first_not_of(__str, __pos,
    396 				       traits_type::length(__str));
    397       }
    398 
    399       constexpr size_type
    400       find_last_not_of(basic_string_view __str,
    401 		       size_type __pos = npos) const noexcept
    402       { return this->find_last_not_of(__str._M_str, __pos, __str._M_len); }
    403 
    404       constexpr size_type
    405       find_last_not_of(_CharT __c, size_type __pos = npos) const noexcept;
    406 
    407       constexpr size_type
    408       find_last_not_of(const _CharT* __str,
    409 		       size_type __pos, size_type __n) const;
    410 
    411       constexpr size_type
    412       find_last_not_of(const _CharT* __str,
    413 		       size_type __pos = npos) const noexcept
    414       {
    415 	return this->find_last_not_of(__str, __pos,
    416 				      traits_type::length(__str));
    417       }
    418 
    419     private:
    420 
    421       static constexpr int
    422       _S_compare(size_type __n1, size_type __n2) noexcept
    423       {
    424 	return difference_type(__n1 - __n2) > std::numeric_limits<int>::max()
    425 	     ? std::numeric_limits<int>::max()
    426 	     : difference_type(__n1 - __n2) < std::numeric_limits<int>::min()
    427 	     ? std::numeric_limits<int>::min()
    428 	     : static_cast<int>(difference_type(__n1 - __n2));
    429       }
    430 
    431       size_t	    _M_len;
    432       const _CharT* _M_str;
    433     };
    434 
    435   // [string.view.comparison], non-member basic_string_view comparison functions
    436 
    437   // Several of these functions use type_identity_t to create a non-deduced
    438   // context, so that only one argument participates in template argument
    439   // deduction and the other argument gets implicitly converted to the deduced
    440   // type (see N3766).
    441 
    442   template<typename _CharT, typename _Traits>
    443     constexpr bool
    444     operator==(basic_string_view<_CharT, _Traits> __x,
    445                basic_string_view<_CharT, _Traits> __y) noexcept
    446     { return __x.size() == __y.size() && __x.compare(__y) == 0; }
    447 
    448   template<typename _CharT, typename _Traits>
    449     constexpr bool
    450     operator==(basic_string_view<_CharT, _Traits> __x,
    451                __type_identity_t<basic_string_view<_CharT, _Traits>> __y)
    452     noexcept
    453     { return __x.size() == __y.size() && __x.compare(__y) == 0; }
    454 
    455   template<typename _CharT, typename _Traits>
    456     constexpr bool
    457     operator==(__type_identity_t<basic_string_view<_CharT, _Traits>> __x,
    458                basic_string_view<_CharT, _Traits> __y) noexcept
    459     { return __x.size() == __y.size() && __x.compare(__y) == 0; }
    460 
    461   template<typename _CharT, typename _Traits>
    462     constexpr bool
    463     operator!=(basic_string_view<_CharT, _Traits> __x,
    464                basic_string_view<_CharT, _Traits> __y) noexcept
    465     { return !(__x == __y); }
    466 
    467   template<typename _CharT, typename _Traits>
    468     constexpr bool
    469     operator!=(basic_string_view<_CharT, _Traits> __x,
    470                __type_identity_t<basic_string_view<_CharT, _Traits>> __y)
    471     noexcept
    472     { return !(__x == __y); }
    473 
    474   template<typename _CharT, typename _Traits>
    475     constexpr bool
    476     operator!=(__type_identity_t<basic_string_view<_CharT, _Traits>> __x,
    477                basic_string_view<_CharT, _Traits> __y) noexcept
    478     { return !(__x == __y); }
    479 
    480   template<typename _CharT, typename _Traits>
    481     constexpr bool
    482     operator< (basic_string_view<_CharT, _Traits> __x,
    483                basic_string_view<_CharT, _Traits> __y) noexcept
    484     { return __x.compare(__y) < 0; }
    485 
    486   template<typename _CharT, typename _Traits>
    487     constexpr bool
    488     operator< (basic_string_view<_CharT, _Traits> __x,
    489                __type_identity_t<basic_string_view<_CharT, _Traits>> __y)
    490     noexcept
    491     { return __x.compare(__y) < 0; }
    492 
    493   template<typename _CharT, typename _Traits>
    494     constexpr bool
    495     operator< (__type_identity_t<basic_string_view<_CharT, _Traits>> __x,
    496                basic_string_view<_CharT, _Traits> __y) noexcept
    497     { return __x.compare(__y) < 0; }
    498 
    499   template<typename _CharT, typename _Traits>
    500     constexpr bool
    501     operator> (basic_string_view<_CharT, _Traits> __x,
    502                basic_string_view<_CharT, _Traits> __y) noexcept
    503     { return __x.compare(__y) > 0; }
    504 
    505   template<typename _CharT, typename _Traits>
    506     constexpr bool
    507     operator> (basic_string_view<_CharT, _Traits> __x,
    508                __type_identity_t<basic_string_view<_CharT, _Traits>> __y)
    509     noexcept
    510     { return __x.compare(__y) > 0; }
    511 
    512   template<typename _CharT, typename _Traits>
    513     constexpr bool
    514     operator> (__type_identity_t<basic_string_view<_CharT, _Traits>> __x,
    515                basic_string_view<_CharT, _Traits> __y) noexcept
    516     { return __x.compare(__y) > 0; }
    517 
    518   template<typename _CharT, typename _Traits>
    519     constexpr bool
    520     operator<=(basic_string_view<_CharT, _Traits> __x,
    521                basic_string_view<_CharT, _Traits> __y) noexcept
    522     { return __x.compare(__y) <= 0; }
    523 
    524   template<typename _CharT, typename _Traits>
    525     constexpr bool
    526     operator<=(basic_string_view<_CharT, _Traits> __x,
    527                __type_identity_t<basic_string_view<_CharT, _Traits>> __y)
    528     noexcept
    529     { return __x.compare(__y) <= 0; }
    530 
    531   template<typename _CharT, typename _Traits>
    532     constexpr bool
    533     operator<=(__type_identity_t<basic_string_view<_CharT, _Traits>> __x,
    534                basic_string_view<_CharT, _Traits> __y) noexcept
    535     { return __x.compare(__y) <= 0; }
    536 
    537   template<typename _CharT, typename _Traits>
    538     constexpr bool
    539     operator>=(basic_string_view<_CharT, _Traits> __x,
    540                basic_string_view<_CharT, _Traits> __y) noexcept
    541     { return __x.compare(__y) >= 0; }
    542 
    543   template<typename _CharT, typename _Traits>
    544     constexpr bool
    545     operator>=(basic_string_view<_CharT, _Traits> __x,
    546                __type_identity_t<basic_string_view<_CharT, _Traits>> __y)
    547     noexcept
    548     { return __x.compare(__y) >= 0; }
    549 
    550   template<typename _CharT, typename _Traits>
    551     constexpr bool
    552     operator>=(__type_identity_t<basic_string_view<_CharT, _Traits>> __x,
    553                basic_string_view<_CharT, _Traits> __y) noexcept
    554     { return __x.compare(__y) >= 0; }
    555 
    556   // [string.view.io], Inserters and extractors
    557   template<typename _CharT, typename _Traits>
    558     inline basic_ostream<_CharT, _Traits>&
    559     operator<<(basic_ostream<_CharT, _Traits>& __os,
    560 	       basic_string_view<_CharT,_Traits> __str)
    561     { return __ostream_insert(__os, __str.data(), __str.size()); }
    562 
    563 
    564   // basic_string_view typedef names
    565 
    566   using string_view = basic_string_view<char>;
    567   using wstring_view = basic_string_view<wchar_t>;
    568 #ifdef _GLIBCXX_USE_CHAR8_T
    569   using u8string_view = basic_string_view<char8_t>;
    570 #endif
    571   using u16string_view = basic_string_view<char16_t>;
    572   using u32string_view = basic_string_view<char32_t>;
    573 } // namespace fundamentals_v1
    574 } // namespace experimental
    575 
    576 
    577   // [string.view.hash], hash support:
    578   template<typename _Tp>
    579     struct hash;
    580 
    581   template<>
    582     struct hash<experimental::string_view>
    583     : public __hash_base<size_t, experimental::string_view>
    584     {
    585       size_t
    586       operator()(const experimental::string_view& __str) const noexcept
    587       { return std::_Hash_impl::hash(__str.data(), __str.length()); }
    588     };
    589 
    590   template<>
    591     struct __is_fast_hash<hash<experimental::string_view>> : std::false_type
    592     { };
    593 
    594   template<>
    595     struct hash<experimental::wstring_view>
    596     : public __hash_base<size_t, wstring>
    597     {
    598       size_t
    599       operator()(const experimental::wstring_view& __s) const noexcept
    600       { return std::_Hash_impl::hash(__s.data(),
    601                                      __s.length() * sizeof(wchar_t)); }
    602     };
    603 
    604   template<>
    605     struct __is_fast_hash<hash<experimental::wstring_view>> : std::false_type
    606     { };
    607 
    608 #ifdef _GLIBCXX_USE_CHAR8_T
    609   template<>
    610     struct hash<experimental::u8string_view>
    611     : public __hash_base<size_t, experimental::u8string_view>
    612     {
    613       size_t
    614       operator()(const experimental::u8string_view& __s) const noexcept
    615       { return std::_Hash_impl::hash(__s.data(), __s.length()); }
    616     };
    617 
    618   template<>
    619     struct __is_fast_hash<hash<experimental::u8string_view>> : std::false_type
    620     { };
    621 #endif
    622 
    623   template<>
    624     struct hash<experimental::u16string_view>
    625     : public __hash_base<size_t, experimental::u16string_view>
    626     {
    627       size_t
    628       operator()(const experimental::u16string_view& __s) const noexcept
    629       { return std::_Hash_impl::hash(__s.data(),
    630                                      __s.length() * sizeof(char16_t)); }
    631     };
    632 
    633   template<>
    634     struct __is_fast_hash<hash<experimental::u16string_view>> : std::false_type
    635     { };
    636 
    637   template<>
    638     struct hash<experimental::u32string_view>
    639     : public __hash_base<size_t, experimental::u32string_view>
    640     {
    641       size_t
    642       operator()(const experimental::u32string_view& __s) const noexcept
    643       { return std::_Hash_impl::hash(__s.data(),
    644                                      __s.length() * sizeof(char32_t)); }
    645     };
    646 
    647   template<>
    648     struct __is_fast_hash<hash<experimental::u32string_view>> : std::false_type
    649     { };
    650 
    651 namespace experimental
    652 {
    653   // I added these EMSR.
    654   inline namespace literals
    655   {
    656   inline namespace string_view_literals
    657   {
    658 #pragma GCC diagnostic push
    659 #pragma GCC diagnostic ignored "-Wliteral-suffix"
    660     inline constexpr basic_string_view<char>
    661     operator""sv(const char* __str, size_t __len) noexcept
    662     { return basic_string_view<char>{__str, __len}; }
    663 
    664     inline constexpr basic_string_view<wchar_t>
    665     operator""sv(const wchar_t* __str, size_t __len) noexcept
    666     { return basic_string_view<wchar_t>{__str, __len}; }
    667 
    668 #ifdef _GLIBCXX_USE_CHAR8_T
    669     inline constexpr basic_string_view<char8_t>
    670     operator""sv(const char8_t* __str, size_t __len) noexcept
    671     { return basic_string_view<char8_t>{__str, __len}; }
    672 #endif
    673 
    674     inline constexpr basic_string_view<char16_t>
    675     operator""sv(const char16_t* __str, size_t __len) noexcept
    676     { return basic_string_view<char16_t>{__str, __len}; }
    677 
    678     inline constexpr basic_string_view<char32_t>
    679     operator""sv(const char32_t* __str, size_t __len) noexcept
    680     { return basic_string_view<char32_t>{__str, __len}; }
    681 #pragma GCC diagnostic pop
    682   } // namespace string_literals
    683   } // namespace literals
    684 } // namespace experimental
    685 
    686 #if __cpp_lib_concepts
    687   namespace ranges
    688   {
    689     // Opt-in to borrowed_range concept
    690     template<typename _CharT, typename _Traits>
    691       inline constexpr bool
    692 	enable_borrowed_range<experimental::basic_string_view<_CharT, _Traits>>
    693 	  = true;
    694 
    695     // Opt-in to view concept
    696     template<typename _CharT, typename _Traits>
    697       inline constexpr bool
    698 	enable_view<experimental::basic_string_view<_CharT, _Traits>> = true;
    699   }
    700 #endif
    701 
    702 _GLIBCXX_END_NAMESPACE_VERSION
    703 } // namespace std
    704 
    705 #include <experimental/bits/string_view.tcc>
    706 
    707 #endif // __cplusplus <= 201103L
    708 
    709 #endif // _GLIBCXX_EXPERIMENTAL_STRING_VIEW
    710