libstdc++
experimental/string_view
Go to the documentation of this file.
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