| // Components for manipulating non-owning sequences of characters -*- C++ -*- | |
| // Copyright (C) 2013-2026 Free Software Foundation, Inc. | |
| // | |
| // This file is part of the GNU ISO C++ Library. This library is free | |
| // software; you can redistribute it and/or modify it under the | |
| // terms of the GNU General Public License as published by the | |
| // Free Software Foundation; either version 3, or (at your option) | |
| // any later version. | |
| // This library is distributed in the hope that it will be useful, | |
| // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| // GNU General Public License for more details. | |
| // Under Section 7 of GPL version 3, you are granted additional | |
| // permissions described in the GCC Runtime Library Exception, version | |
| // 3.1, as published by the Free Software Foundation. | |
| // You should have received a copy of the GNU General Public License and | |
| // a copy of the GCC Runtime Library Exception along with this program; | |
| // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see | |
| // <http://www.gnu.org/licenses/>. | |
| /** @file include/string_view | |
| * This is a Standard C++ Library header. | |
| */ | |
| // | |
| // N3762 basic_string_view library | |
| // | |
| #ifndef _GLIBCXX_STRING_VIEW | |
| #define _GLIBCXX_STRING_VIEW 1 | |
| #ifdef _GLIBCXX_SYSHDR | |
| #pragma GCC system_header | |
| #endif | |
| #define __glibcxx_want_constexpr_char_traits | |
| #define __glibcxx_want_constexpr_string_view | |
| #define __glibcxx_want_freestanding_string_view | |
| #define __glibcxx_want_hardened_basic_string_view | |
| #define __glibcxx_want_starts_ends_with | |
| #define __glibcxx_want_string_contains | |
| #define __glibcxx_want_string_subview | |
| #define __glibcxx_want_string_view | |
| #include <bits/version.h> | |
| #if __cplusplus >= 201703L | |
| #include <bits/char_traits.h> | |
| #ifndef __glibcxx_exc_in_string | |
| #define __glibcxx_exc_in_string 2 | |
| #include <bits/stdexcept_throw.h> | |
| #endif | |
| #include <bits/functional_hash.h> | |
| #include <bits/range_access.h> | |
| #include <bits/stl_algobase.h> | |
| #include <ext/numeric_traits.h> | |
| #if __cplusplus >= 202002L | |
| # include <bits/ranges_base.h> | |
| #endif | |
| #if _GLIBCXX_HOSTED | |
| # include <bits/iosfwd.h> | |
| # include <bits/ostream_insert.h> | |
| #endif | |
| namespace std _GLIBCXX_VISIBILITY(default) | |
| { | |
| _GLIBCXX_BEGIN_NAMESPACE_VERSION | |
| // Helper for basic_string and basic_string_view members. | |
| constexpr size_t | |
| __sv_check(size_t __size, size_t __pos, const char* __s) | |
| { | |
| if (__pos > __size) | |
| __throw_out_of_range_fmt(__N("%s: __pos (which is %zu) > __size " | |
| "(which is %zu)"), __s, __pos, __size); | |
| return __pos; | |
| } | |
| // Helper for basic_string members. | |
| // NB: __sv_limit doesn't check for a bad __pos value. | |
| constexpr size_t | |
| __sv_limit(size_t __size, size_t __pos, size_t __off) noexcept | |
| { | |
| const bool __testoff = __off < __size - __pos; | |
| return __testoff ? __off : __size - __pos; | |
| } | |
| /** | |
| * @class basic_string_view <string_view> | |
| * @brief A non-owning reference to a string. | |
| * | |
| * @ingroup strings | |
| * @ingroup sequences | |
| * | |
| * @tparam _CharT Type of character | |
| * @tparam _Traits Traits for character type, defaults to | |
| * char_traits<_CharT>. | |
| * | |
| * A basic_string_view looks like this: | |
| * | |
| * @code | |
| * _CharT* _M_str | |
| * size_t _M_len | |
| * @endcode | |
| */ | |
| template<typename _CharT, typename _Traits = std::char_traits<_CharT>> | |
| class basic_string_view | |
| { | |
| static_assert(!is_array_v<_CharT>); | |
| static_assert(is_trivially_copyable_v<_CharT> | |
| && is_trivially_default_constructible_v<_CharT> | |
| && is_standard_layout_v<_CharT>); | |
| static_assert(is_same_v<_CharT, typename _Traits::char_type>); | |
| public: | |
| // types | |
| using traits_type = _Traits; | |
| using value_type = _CharT; | |
| using pointer = value_type*; | |
| using const_pointer = const value_type*; | |
| using reference = value_type&; | |
| using const_reference = const value_type&; | |
| using const_iterator = const value_type*; | |
| using iterator = const_iterator; | |
| using const_reverse_iterator = std::reverse_iterator<const_iterator>; | |
| using reverse_iterator = const_reverse_iterator; | |
| using size_type = size_t; | |
| using difference_type = ptrdiff_t; | |
| static constexpr size_type npos = size_type(-1); | |
| // [string.view.cons], construction and assignment | |
| constexpr | |
| basic_string_view() noexcept | |
| : _M_len{0}, _M_str{nullptr} | |
| { } | |
| constexpr basic_string_view(const basic_string_view&) noexcept = default; | |
| [[__gnu__::__nonnull__]] | |
| constexpr | |
| basic_string_view(const _CharT* __str) noexcept | |
| : _M_len{traits_type::length(__str)}, | |
| _M_str{__str} | |
| { } | |
| constexpr | |
| basic_string_view(const _CharT* __str, size_type __len) noexcept | |
| : _M_len{__len}, _M_str{__str} | |
| { } | |
| #if __cplusplus >= 202002L && __cpp_lib_concepts | |
| template<contiguous_iterator _It, sized_sentinel_for<_It> _End> | |
| requires same_as<iter_value_t<_It>, _CharT> | |
| && (!convertible_to<_End, size_type>) | |
| constexpr | |
| basic_string_view(_It __first, _End __last) | |
| noexcept(noexcept(__last - __first)) | |
| : _M_len(__last - __first), _M_str(std::to_address(__first)) | |
| { } | |
| #if __cplusplus > 202002L | |
| template<typename _Range, typename _DRange = remove_cvref_t<_Range>> | |
| requires (!is_same_v<_DRange, basic_string_view>) | |
| && ranges::contiguous_range<_Range> | |
| && ranges::sized_range<_Range> | |
| && is_same_v<ranges::range_value_t<_Range>, _CharT> | |
| && (!is_convertible_v<_Range, const _CharT*>) | |
| && (!requires (_DRange& __d) { | |
| __d.operator ::std::basic_string_view<_CharT, _Traits>(); | |
| }) | |
| constexpr explicit | |
| basic_string_view(_Range&& __r) | |
| noexcept(noexcept(ranges::size(__r)) && noexcept(ranges::data(__r))) | |
| : _M_len(ranges::size(__r)), _M_str(ranges::data(__r)) | |
| { } | |
| basic_string_view(nullptr_t) = delete; | |
| #endif // C++23 | |
| #endif // C++20 | |
| constexpr basic_string_view& | |
| operator=(const basic_string_view&) noexcept = default; | |
| // [string.view.iterators], iterator support | |
| [[nodiscard]] | |
| constexpr const_iterator | |
| begin() const noexcept | |
| { return this->_M_str; } | |
| [[nodiscard]] | |
| constexpr const_iterator | |
| end() const noexcept | |
| { return this->_M_str + this->_M_len; } | |
| [[nodiscard]] | |
| constexpr const_iterator | |
| cbegin() const noexcept | |
| { return this->_M_str; } | |
| [[nodiscard]] | |
| constexpr const_iterator | |
| cend() const noexcept | |
| { return this->_M_str + this->_M_len; } | |
| [[nodiscard]] | |
| constexpr const_reverse_iterator | |
| rbegin() const noexcept | |
| { return const_reverse_iterator(this->end()); } | |
| [[nodiscard]] | |
| constexpr const_reverse_iterator | |
| rend() const noexcept | |
| { return const_reverse_iterator(this->begin()); } | |
| [[nodiscard]] | |
| constexpr const_reverse_iterator | |
| crbegin() const noexcept | |
| { return const_reverse_iterator(this->end()); } | |
| [[nodiscard]] | |
| constexpr const_reverse_iterator | |
| crend() const noexcept | |
| { return const_reverse_iterator(this->begin()); } | |
| // [string.view.capacity], capacity | |
| [[nodiscard]] | |
| constexpr size_type | |
| size() const noexcept | |
| { return this->_M_len; } | |
| [[nodiscard]] | |
| constexpr size_type | |
| length() const noexcept | |
| { return _M_len; } | |
| [[nodiscard]] | |
| constexpr size_type | |
| max_size() const noexcept | |
| { | |
| return (npos - sizeof(size_type) - sizeof(void*)) | |
| / sizeof(value_type) / 4; | |
| } | |
| [[nodiscard]] | |
| constexpr bool | |
| empty() const noexcept | |
| { return this->_M_len == 0; } | |
| // [string.view.access], element access | |
| [[nodiscard]] | |
| constexpr const_reference | |
| operator[](size_type __pos) const noexcept | |
| { | |
| __glibcxx_assert(__pos < this->_M_len); | |
| return *(this->_M_str + __pos); | |
| } | |
| [[nodiscard]] | |
| constexpr const_reference | |
| at(size_type __pos) const | |
| { | |
| if (__pos >= _M_len) | |
| __throw_out_of_range_fmt(__N("basic_string_view::at: __pos " | |
| "(which is %zu) >= this->size() " | |
| "(which is %zu)"), __pos, this->size()); | |
| return *(this->_M_str + __pos); | |
| } | |
| [[nodiscard]] | |
| constexpr const_reference | |
| front() const noexcept | |
| { | |
| __glibcxx_assert(this->_M_len > 0); | |
| return *this->_M_str; | |
| } | |
| [[nodiscard]] | |
| constexpr const_reference | |
| back() const noexcept | |
| { | |
| __glibcxx_assert(this->_M_len > 0); | |
| return *(this->_M_str + this->_M_len - 1); | |
| } | |
| [[nodiscard]] | |
| constexpr const_pointer | |
| data() const noexcept | |
| { return this->_M_str; } | |
| // [string.view.modifiers], modifiers: | |
| constexpr void | |
| remove_prefix(size_type __n) noexcept | |
| { | |
| __glibcxx_assert(this->_M_len >= __n); | |
| this->_M_str += __n; | |
| this->_M_len -= __n; | |
| } | |
| constexpr void | |
| remove_suffix(size_type __n) noexcept | |
| { | |
| __glibcxx_assert(this->_M_len >= __n); | |
| this->_M_len -= __n; | |
| } | |
| constexpr void | |
| swap(basic_string_view& __sv) noexcept | |
| { | |
| auto __tmp = *this; | |
| *this = __sv; | |
| __sv = __tmp; | |
| } | |
| // [string.view.ops], string operations: | |
| _GLIBCXX20_CONSTEXPR | |
| size_type | |
| copy(_CharT* __str, size_type __n, size_type __pos = 0) const | |
| { | |
| __glibcxx_requires_string_len(__str, __n); | |
| __pos = std::__sv_check(size(), __pos, "basic_string_view::copy"); | |
| const size_type __rlen = std::min<size_t>(__n, _M_len - __pos); | |
| // _GLIBCXX_RESOLVE_LIB_DEFECTS | |
| // 2777. basic_string_view::copy should use char_traits::copy | |
| traits_type::copy(__str, data() + __pos, __rlen); | |
| return __rlen; | |
| } | |
| [[nodiscard]] | |
| constexpr basic_string_view | |
| substr(size_type __pos = 0, size_type __n = npos) const noexcept(false) | |
| { | |
| __pos = std::__sv_check(size(), __pos, "basic_string_view::substr"); | |
| const size_type __rlen = std::min<size_t>(__n, _M_len - __pos); | |
| return basic_string_view{_M_str + __pos, __rlen}; | |
| } | |
| #ifdef __glibcxx_string_subview // >= C++26 | |
| [[nodiscard]] | |
| constexpr basic_string_view | |
| subview(size_type __pos = 0, size_type __n = npos) const | |
| { return substr(__pos, __n); } | |
| #endif | |
| [[nodiscard]] | |
| constexpr int | |
| compare(basic_string_view __str) const noexcept | |
| { | |
| const size_type __rlen = std::min(this->_M_len, __str._M_len); | |
| int __ret = traits_type::compare(this->_M_str, __str._M_str, __rlen); | |
| if (__ret == 0) | |
| __ret = _S_compare(this->_M_len, __str._M_len); | |
| return __ret; | |
| } | |
| [[nodiscard]] | |
| constexpr int | |
| compare(size_type __pos1, size_type __n1, basic_string_view __str) const | |
| { return this->substr(__pos1, __n1).compare(__str); } | |
| [[nodiscard]] | |
| constexpr int | |
| compare(size_type __pos1, size_type __n1, | |
| basic_string_view __str, size_type __pos2, size_type __n2) const | |
| { | |
| return this->substr(__pos1, __n1).compare(__str.substr(__pos2, __n2)); | |
| } | |
| [[nodiscard, __gnu__::__nonnull__]] | |
| constexpr int | |
| compare(const _CharT* __str) const noexcept | |
| { return this->compare(basic_string_view{__str}); } | |
| [[nodiscard, __gnu__::__nonnull__]] | |
| constexpr int | |
| compare(size_type __pos1, size_type __n1, const _CharT* __str) const | |
| { return this->substr(__pos1, __n1).compare(basic_string_view{__str}); } | |
| [[nodiscard]] | |
| constexpr int | |
| compare(size_type __pos1, size_type __n1, | |
| const _CharT* __str, size_type __n2) const noexcept(false) | |
| { | |
| return this->substr(__pos1, __n1) | |
| .compare(basic_string_view(__str, __n2)); | |
| } | |
| #ifdef __cpp_lib_starts_ends_with // C++ >= 20 | |
| [[nodiscard]] | |
| constexpr bool | |
| starts_with(basic_string_view __x) const noexcept | |
| { | |
| return _M_len >= __x._M_len | |
| && traits_type::compare(_M_str, __x._M_str, __x._M_len) == 0; | |
| } | |
| [[nodiscard]] | |
| constexpr bool | |
| starts_with(_CharT __x) const noexcept | |
| { return !this->empty() && traits_type::eq(this->front(), __x); } | |
| [[nodiscard, __gnu__::__nonnull__]] | |
| constexpr bool | |
| starts_with(const _CharT* __x) const noexcept | |
| { return this->starts_with(basic_string_view(__x)); } | |
| [[nodiscard]] | |
| constexpr bool | |
| ends_with(basic_string_view __x) const noexcept | |
| { | |
| const auto __len = this->size(); | |
| const auto __xlen = __x.size(); | |
| return __len >= __xlen | |
| && traits_type::compare(end() - __xlen, __x.data(), __xlen) == 0; | |
| } | |
| [[nodiscard]] | |
| constexpr bool | |
| ends_with(_CharT __x) const noexcept | |
| { return !this->empty() && traits_type::eq(this->back(), __x); } | |
| [[nodiscard, __gnu__::__nonnull__]] | |
| constexpr bool | |
| ends_with(const _CharT* __x) const noexcept | |
| { return this->ends_with(basic_string_view(__x)); } | |
| #endif // __cpp_lib_starts_ends_with | |
| #if __cplusplus > 202002L | |
| #if _GLIBCXX_HOSTED && !defined(__cpp_lib_string_contains) | |
| // This FTM is not freestanding as it also implies matching <string> | |
| // support, and <string> is omitted from the freestanding subset. | |
| # error "libstdc++ bug: string_contains not defined when it should be" | |
| #endif // HOSTED | |
| [[nodiscard]] | |
| constexpr bool | |
| contains(basic_string_view __x) const noexcept | |
| { return this->find(__x) != npos; } | |
| [[nodiscard]] | |
| constexpr bool | |
| contains(_CharT __x) const noexcept | |
| { return this->find(__x) != npos; } | |
| [[nodiscard, __gnu__::__nonnull__]] | |
| constexpr bool | |
| contains(const _CharT* __x) const noexcept | |
| { return this->find(__x) != npos; } | |
| #endif // C++23 | |
| // [string.view.find], searching | |
| [[nodiscard]] | |
| constexpr size_type | |
| find(basic_string_view __str, size_type __pos = 0) const noexcept | |
| { return this->find(__str._M_str, __pos, __str._M_len); } | |
| [[nodiscard]] | |
| constexpr size_type | |
| find(_CharT __c, size_type __pos = 0) const noexcept; | |
| [[nodiscard]] | |
| constexpr size_type | |
| find(const _CharT* __str, size_type __pos, size_type __n) const noexcept; | |
| [[nodiscard, __gnu__::__nonnull__]] | |
| constexpr size_type | |
| find(const _CharT* __str, size_type __pos = 0) const noexcept | |
| { return this->find(__str, __pos, traits_type::length(__str)); } | |
| [[nodiscard]] | |
| constexpr size_type | |
| rfind(basic_string_view __str, size_type __pos = npos) const noexcept | |
| { return this->rfind(__str._M_str, __pos, __str._M_len); } | |
| [[nodiscard]] | |
| constexpr size_type | |
| rfind(_CharT __c, size_type __pos = npos) const noexcept; | |
| [[nodiscard]] | |
| constexpr size_type | |
| rfind(const _CharT* __str, size_type __pos, size_type __n) const noexcept; | |
| [[nodiscard, __gnu__::__nonnull__]] | |
| constexpr size_type | |
| rfind(const _CharT* __str, size_type __pos = npos) const noexcept | |
| { return this->rfind(__str, __pos, traits_type::length(__str)); } | |
| [[nodiscard]] | |
| constexpr size_type | |
| find_first_of(basic_string_view __str, size_type __pos = 0) const noexcept | |
| { return this->find_first_of(__str._M_str, __pos, __str._M_len); } | |
| [[nodiscard]] | |
| constexpr size_type | |
| find_first_of(_CharT __c, size_type __pos = 0) const noexcept | |
| { return this->find(__c, __pos); } | |
| [[nodiscard]] | |
| constexpr size_type | |
| find_first_of(const _CharT* __str, size_type __pos, | |
| size_type __n) const noexcept; | |
| [[nodiscard, __gnu__::__nonnull__]] | |
| constexpr size_type | |
| find_first_of(const _CharT* __str, size_type __pos = 0) const noexcept | |
| { return this->find_first_of(__str, __pos, traits_type::length(__str)); } | |
| [[nodiscard]] | |
| constexpr size_type | |
| find_last_of(basic_string_view __str, | |
| size_type __pos = npos) const noexcept | |
| { return this->find_last_of(__str._M_str, __pos, __str._M_len); } | |
| [[nodiscard]] | |
| constexpr size_type | |
| find_last_of(_CharT __c, size_type __pos=npos) const noexcept | |
| { return this->rfind(__c, __pos); } | |
| [[nodiscard]] | |
| constexpr size_type | |
| find_last_of(const _CharT* __str, size_type __pos, | |
| size_type __n) const noexcept; | |
| [[nodiscard, __gnu__::__nonnull__]] | |
| constexpr size_type | |
| find_last_of(const _CharT* __str, size_type __pos = npos) const noexcept | |
| { return this->find_last_of(__str, __pos, traits_type::length(__str)); } | |
| [[nodiscard]] | |
| constexpr size_type | |
| find_first_not_of(basic_string_view __str, | |
| size_type __pos = 0) const noexcept | |
| { return this->find_first_not_of(__str._M_str, __pos, __str._M_len); } | |
| [[nodiscard]] | |
| constexpr size_type | |
| find_first_not_of(_CharT __c, size_type __pos = 0) const noexcept; | |
| [[nodiscard]] | |
| constexpr size_type | |
| find_first_not_of(const _CharT* __str, | |
| size_type __pos, size_type __n) const noexcept; | |
| [[nodiscard, __gnu__::__nonnull__]] | |
| constexpr size_type | |
| find_first_not_of(const _CharT* __str, size_type __pos = 0) const noexcept | |
| { | |
| return this->find_first_not_of(__str, __pos, | |
| traits_type::length(__str)); | |
| } | |
| [[nodiscard]] | |
| constexpr size_type | |
| find_last_not_of(basic_string_view __str, | |
| size_type __pos = npos) const noexcept | |
| { return this->find_last_not_of(__str._M_str, __pos, __str._M_len); } | |
| [[nodiscard]] | |
| constexpr size_type | |
| find_last_not_of(_CharT __c, size_type __pos = npos) const noexcept; | |
| [[nodiscard]] | |
| constexpr size_type | |
| find_last_not_of(const _CharT* __str, | |
| size_type __pos, size_type __n) const noexcept; | |
| [[nodiscard, __gnu__::__nonnull__]] | |
| constexpr size_type | |
| find_last_not_of(const _CharT* __str, | |
| size_type __pos = npos) const noexcept | |
| { | |
| return this->find_last_not_of(__str, __pos, | |
| traits_type::length(__str)); | |
| } | |
| private: | |
| static constexpr int | |
| _S_compare(size_type __n1, size_type __n2) noexcept | |
| { | |
| using __limits = __gnu_cxx::__int_traits<int>; | |
| const difference_type __diff = __n1 - __n2; | |
| if (__diff > __limits::__max) | |
| return __limits::__max; | |
| if (__diff < __limits::__min) | |
| return __limits::__min; | |
| return static_cast<int>(__diff); | |
| } | |
| size_t _M_len; | |
| const _CharT* _M_str; | |
| }; | |
| #if __cplusplus > 201703L && __cpp_lib_concepts && __cpp_deduction_guides | |
| template<contiguous_iterator _It, sized_sentinel_for<_It> _End> | |
| basic_string_view(_It, _End) -> basic_string_view<iter_value_t<_It>>; | |
| #if __cplusplus > 202002L | |
| template<ranges::contiguous_range _Range> | |
| basic_string_view(_Range&&) | |
| -> basic_string_view<ranges::range_value_t<_Range>>; | |
| #endif | |
| #endif | |
| // [string.view.comparison], non-member basic_string_view comparison function | |
| // Several of these functions use type_identity_t to create a non-deduced | |
| // context, so that only one argument participates in template argument | |
| // deduction and the other argument gets implicitly converted to the deduced | |
| // type (see N3766). | |
| #if __cpp_lib_three_way_comparison | |
| // _GLIBCXX_RESOLVE_LIB_DEFECTS | |
| // 3950. std::basic_string_view comparison operators are overspecified | |
| template<typename _CharT, typename _Traits> | |
| [[nodiscard]] | |
| constexpr bool | |
| operator==(basic_string_view<_CharT, _Traits> __x, | |
| type_identity_t<basic_string_view<_CharT, _Traits>> __y) | |
| noexcept | |
| { return __x.size() == __y.size() && __x.compare(__y) == 0; } | |
| template<typename _CharT, typename _Traits> | |
| [[nodiscard]] | |
| constexpr auto | |
| operator<=>(basic_string_view<_CharT, _Traits> __x, | |
| type_identity_t<basic_string_view<_CharT, _Traits>> __y) | |
| noexcept | |
| -> decltype(__detail::__char_traits_cmp_cat<_Traits>(0)) | |
| { return __detail::__char_traits_cmp_cat<_Traits>(__x.compare(__y)); } | |
| #else | |
| template<typename _CharT, typename _Traits> | |
| [[nodiscard]] | |
| constexpr bool | |
| operator==(basic_string_view<_CharT, _Traits> __x, | |
| __type_identity_t<basic_string_view<_CharT, _Traits>> __y) | |
| noexcept | |
| { return __x.size() == __y.size() && __x.compare(__y) == 0; } | |
| template<typename _CharT, typename _Traits> | |
| [[nodiscard]] | |
| constexpr bool | |
| operator==(basic_string_view<_CharT, _Traits> __x, | |
| basic_string_view<_CharT, _Traits> __y) noexcept | |
| { return __x.size() == __y.size() && __x.compare(__y) == 0; } | |
| template<typename _CharT, typename _Traits> | |
| [[nodiscard]] | |
| constexpr bool | |
| operator==(__type_identity_t<basic_string_view<_CharT, _Traits>> __x, | |
| basic_string_view<_CharT, _Traits> __y) noexcept | |
| { return __x.size() == __y.size() && __x.compare(__y) == 0; } | |
| template<typename _CharT, typename _Traits> | |
| [[nodiscard]] | |
| constexpr bool | |
| operator!=(basic_string_view<_CharT, _Traits> __x, | |
| basic_string_view<_CharT, _Traits> __y) noexcept | |
| { return !(__x == __y); } | |
| template<typename _CharT, typename _Traits> | |
| [[nodiscard]] | |
| constexpr bool | |
| operator!=(basic_string_view<_CharT, _Traits> __x, | |
| __type_identity_t<basic_string_view<_CharT, _Traits>> __y) | |
| noexcept | |
| { return !(__x == __y); } | |
| template<typename _CharT, typename _Traits> | |
| [[nodiscard]] | |
| constexpr bool | |
| operator!=(__type_identity_t<basic_string_view<_CharT, _Traits>> __x, | |
| basic_string_view<_CharT, _Traits> __y) noexcept | |
| { return !(__x == __y); } | |
| template<typename _CharT, typename _Traits> | |
| [[nodiscard]] | |
| constexpr bool | |
| operator< (basic_string_view<_CharT, _Traits> __x, | |
| basic_string_view<_CharT, _Traits> __y) noexcept | |
| { return __x.compare(__y) < 0; } | |
| template<typename _CharT, typename _Traits> | |
| [[nodiscard]] | |
| constexpr bool | |
| operator< (basic_string_view<_CharT, _Traits> __x, | |
| __type_identity_t<basic_string_view<_CharT, _Traits>> __y) | |
| noexcept | |
| { return __x.compare(__y) < 0; } | |
| template<typename _CharT, typename _Traits> | |
| [[nodiscard]] | |
| constexpr bool | |
| operator< (__type_identity_t<basic_string_view<_CharT, _Traits>> __x, | |
| basic_string_view<_CharT, _Traits> __y) noexcept | |
| { return __x.compare(__y) < 0; } | |
| template<typename _CharT, typename _Traits> | |
| [[nodiscard]] | |
| constexpr bool | |
| operator> (basic_string_view<_CharT, _Traits> __x, | |
| basic_string_view<_CharT, _Traits> __y) noexcept | |
| { return __x.compare(__y) > 0; } | |
| template<typename _CharT, typename _Traits> | |
| [[nodiscard]] | |
| constexpr bool | |
| operator> (basic_string_view<_CharT, _Traits> __x, | |
| __type_identity_t<basic_string_view<_CharT, _Traits>> __y) | |
| noexcept | |
| { return __x.compare(__y) > 0; } | |
| template<typename _CharT, typename _Traits> | |
| [[nodiscard]] | |
| constexpr bool | |
| operator> (__type_identity_t<basic_string_view<_CharT, _Traits>> __x, | |
| basic_string_view<_CharT, _Traits> __y) noexcept | |
| { return __x.compare(__y) > 0; } | |
| template<typename _CharT, typename _Traits> | |
| [[nodiscard]] | |
| constexpr bool | |
| operator<=(basic_string_view<_CharT, _Traits> __x, | |
| basic_string_view<_CharT, _Traits> __y) noexcept | |
| { return __x.compare(__y) <= 0; } | |
| template<typename _CharT, typename _Traits> | |
| [[nodiscard]] | |
| constexpr bool | |
| operator<=(basic_string_view<_CharT, _Traits> __x, | |
| __type_identity_t<basic_string_view<_CharT, _Traits>> __y) | |
| noexcept | |
| { return __x.compare(__y) <= 0; } | |
| template<typename _CharT, typename _Traits> | |
| [[nodiscard]] | |
| constexpr bool | |
| operator<=(__type_identity_t<basic_string_view<_CharT, _Traits>> __x, | |
| basic_string_view<_CharT, _Traits> __y) noexcept | |
| { return __x.compare(__y) <= 0; } | |
| template<typename _CharT, typename _Traits> | |
| [[nodiscard]] | |
| constexpr bool | |
| operator>=(basic_string_view<_CharT, _Traits> __x, | |
| basic_string_view<_CharT, _Traits> __y) noexcept | |
| { return __x.compare(__y) >= 0; } | |
| template<typename _CharT, typename _Traits> | |
| [[nodiscard]] | |
| constexpr bool | |
| operator>=(basic_string_view<_CharT, _Traits> __x, | |
| __type_identity_t<basic_string_view<_CharT, _Traits>> __y) | |
| noexcept | |
| { return __x.compare(__y) >= 0; } | |
| template<typename _CharT, typename _Traits> | |
| [[nodiscard]] | |
| constexpr bool | |
| operator>=(__type_identity_t<basic_string_view<_CharT, _Traits>> __x, | |
| basic_string_view<_CharT, _Traits> __y) noexcept | |
| { return __x.compare(__y) >= 0; } | |
| #endif // three-way comparison | |
| #if _GLIBCXX_HOSTED | |
| // [string.view.io], Inserters and extractors | |
| template<typename _CharT, typename _Traits> | |
| inline basic_ostream<_CharT, _Traits>& | |
| operator<<(basic_ostream<_CharT, _Traits>& __os, | |
| basic_string_view<_CharT,_Traits> __str) | |
| { return __ostream_insert(__os, __str.data(), __str.size()); } | |
| #endif // HOSTED | |
| // basic_string_view typedef names | |
| using string_view = basic_string_view<char>; | |
| using wstring_view = basic_string_view<wchar_t>; | |
| #ifdef _GLIBCXX_USE_CHAR8_T | |
| using u8string_view = basic_string_view<char8_t>; | |
| #endif | |
| using u16string_view = basic_string_view<char16_t>; | |
| using u32string_view = basic_string_view<char32_t>; | |
| // [string.view.hash], hash support: | |
| template<typename _Tp> | |
| struct hash; | |
| template<> | |
| struct hash<string_view> | |
| : public __hash_base<size_t, string_view> | |
| { | |
| [[nodiscard]] | |
| size_t | |
| operator()(const string_view& __str) const noexcept | |
| { return std::_Hash_impl::hash(__str.data(), __str.length()); } | |
| }; | |
| template<> | |
| struct __is_fast_hash<hash<string_view>> : std::false_type | |
| { }; | |
| template<> | |
| struct hash<wstring_view> | |
| : public __hash_base<size_t, wstring_view> | |
| { | |
| [[nodiscard]] | |
| size_t | |
| operator()(const wstring_view& __s) const noexcept | |
| { return std::_Hash_impl::hash(__s.data(), | |
| __s.length() * sizeof(wchar_t)); } | |
| }; | |
| template<> | |
| struct __is_fast_hash<hash<wstring_view>> : std::false_type | |
| { }; | |
| #ifdef _GLIBCXX_USE_CHAR8_T | |
| template<> | |
| struct hash<u8string_view> | |
| : public __hash_base<size_t, u8string_view> | |
| { | |
| [[nodiscard]] | |
| size_t | |
| operator()(const u8string_view& __str) const noexcept | |
| { return std::_Hash_impl::hash(__str.data(), __str.length()); } | |
| }; | |
| template<> | |
| struct __is_fast_hash<hash<u8string_view>> : std::false_type | |
| { }; | |
| #endif | |
| template<> | |
| struct hash<u16string_view> | |
| : public __hash_base<size_t, u16string_view> | |
| { | |
| [[nodiscard]] | |
| size_t | |
| operator()(const u16string_view& __s) const noexcept | |
| { return std::_Hash_impl::hash(__s.data(), | |
| __s.length() * sizeof(char16_t)); } | |
| }; | |
| template<> | |
| struct __is_fast_hash<hash<u16string_view>> : std::false_type | |
| { }; | |
| template<> | |
| struct hash<u32string_view> | |
| : public __hash_base<size_t, u32string_view> | |
| { | |
| [[nodiscard]] | |
| size_t | |
| operator()(const u32string_view& __s) const noexcept | |
| { return std::_Hash_impl::hash(__s.data(), | |
| __s.length() * sizeof(char32_t)); } | |
| }; | |
| template<> | |
| struct __is_fast_hash<hash<u32string_view>> : std::false_type | |
| { }; | |
| inline namespace literals | |
| { | |
| inline namespace string_view_literals | |
| { | |
| #pragma GCC diagnostic push | |
| #pragma GCC diagnostic ignored "-Wliteral-suffix" | |
| inline constexpr basic_string_view<char> | |
| operator""sv(const char* __str, size_t __len) noexcept | |
| { return basic_string_view<char>{__str, __len}; } | |
| inline constexpr basic_string_view<wchar_t> | |
| operator""sv(const wchar_t* __str, size_t __len) noexcept | |
| { return basic_string_view<wchar_t>{__str, __len}; } | |
| #ifdef _GLIBCXX_USE_CHAR8_T | |
| inline constexpr basic_string_view<char8_t> | |
| operator""sv(const char8_t* __str, size_t __len) noexcept | |
| { return basic_string_view<char8_t>{__str, __len}; } | |
| #endif | |
| inline constexpr basic_string_view<char16_t> | |
| operator""sv(const char16_t* __str, size_t __len) noexcept | |
| { return basic_string_view<char16_t>{__str, __len}; } | |
| inline constexpr basic_string_view<char32_t> | |
| operator""sv(const char32_t* __str, size_t __len) noexcept | |
| { return basic_string_view<char32_t>{__str, __len}; } | |
| #pragma GCC diagnostic pop | |
| } // namespace string_literals | |
| } // namespace literals | |
| #if __cpp_lib_concepts | |
| namespace ranges | |
| { | |
| // Opt-in to borrowed_range concept | |
| template<typename _CharT, typename _Traits> | |
| inline constexpr bool | |
| enable_borrowed_range<basic_string_view<_CharT, _Traits>> = true; | |
| // Opt-in to view concept | |
| template<typename _CharT, typename _Traits> | |
| inline constexpr bool | |
| enable_view<basic_string_view<_CharT, _Traits>> = true; | |
| } | |
| #endif | |
| _GLIBCXX_END_NAMESPACE_VERSION | |
| } // namespace std | |
| #include <bits/string_view.tcc> | |
| #if __glibcxx_exc_in_string == 2 | |
| #undef __glibcxx_exc_in_string | |
| #if (_GLIBCXX_HOSTED && __cpp_exceptions && __cplusplus > 202302L \ | |
| && __cpp_constexpr_exceptions >= 202411L) | |
| #include <bits/stdexcept_throw.h> | |
| #endif | |
| #endif | |
| #endif // C++17 | |
| #endif // _GLIBCXX_STRING_VIEW |