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