//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. // //===----------------------------------------------------------------------===// #ifndef _CUDA_STD_STRING_VIEW #define _CUDA_STD_STRING_VIEW #include #if defined(_CCCL_IMPLICIT_SYSTEM_HEADER_GCC) # pragma GCC system_header #elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_CLANG) # pragma clang system_header #elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_MSVC) # pragma system_header #endif // no system header #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // todo: find a way to get rid of these includes #if _CCCL_HOSTED() # include // for std::basic_string operator<< # if __cpp_lib_string_view >= 201606L # include // for std::basic_string_view operator<< # endif // __cpp_lib_string_view >= 201606L #endif // _CCCL_HOSTED() #include _CCCL_BEGIN_NAMESPACE_CUDA_STD template _CCCL_CONCEPT __cccl_has_basic_sv_conv_operator = _CCCL_REQUIRES_EXPR((_Range, _CharT, _Traits), remove_cvref_t<_Range>& __d)( (__d.operator ::cuda::std::basic_string_view<_CharT, _Traits>())); template _CCCL_CONCEPT __cccl_basic_sv_compatible_range_check_traits = _CCCL_REQUIRES_EXPR((_Range, _CharT, _Traits)) // ( // typename(typename _Range::traits_type), // requires(is_same_v) // ); template _CCCL_CONCEPT __cccl_basic_sv_compatible_range_check_traits_std_ext = #if _CCCL_HOSTED() _CCCL_REQUIRES_EXPR((_Range, _CharT, _Traits)) // ( // typename(typename _Range::traits_type), // requires(is_same_v>), // requires(is_same_v<_Traits, ::cuda::std::char_traits<_CharT>>) // ); #else // ^^^ _CCCL_HOSTED() ^^^ / vvv _CCCL_FREESTANDING() vvv true; #endif // ^^^ _CCCL_FREESTANDING() ^^^ template _CCCL_CONCEPT __cccl_basic_sv_compatible_range = _CCCL_REQUIRES_EXPR((_Range, _CharT, _Traits)) // ( // requires(::cuda::std::ranges::contiguous_range<_Range>), // requires(::cuda::std::ranges::sized_range<_Range>), // requires(is_same_v<::cuda::std::ranges::range_value_t<_Range>, _CharT>), // requires(!(__is_cuda_std_basic_string_view_v> && __cccl_basic_sv_compatible_range_check_traits<_Range, _CharT, _Traits>) ), // requires(!is_convertible_v<_Range, const _CharT*>), // requires(!__cccl_has_basic_sv_conv_operator<_Range, _CharT, _Traits>), // requires(!(__is_std_basic_string_v> && (__cccl_basic_sv_compatible_range_check_traits<_Range, _CharT, _Traits> || __cccl_basic_sv_compatible_range_check_traits_std_ext<_Range, _CharT, _Traits>) )), // requires(!(__is_std_basic_string_view_v> && (__cccl_basic_sv_compatible_range_check_traits<_Range, _CharT, _Traits> || __cccl_basic_sv_compatible_range_check_traits_std_ext<_Range, _CharT, _Traits>) )) // ); template _CCCL_CONCEPT __cccl_basic_sv_is_std_to_cuda_std_char_traits = _CCCL_REQUIRES_EXPR((_Traits, _HostTraits)) // ( // requires(__is_cuda_std_char_traits_v<_Traits>), // requires(__is_std_char_traits_v<_HostTraits>) // ); template class _CCCL_TYPE_VISIBILITY_DEFAULT basic_string_view { public: using traits_type = _Traits; using value_type = _CharT; using pointer = _CharT*; using const_pointer = const _CharT*; using reference = _CharT&; using const_reference = const _CharT&; using const_iterator = const_pointer; using iterator = const_iterator; using const_reverse_iterator = ::cuda::std::reverse_iterator; using reverse_iterator = const_reverse_iterator; using size_type = size_t; using difference_type = ptrdiff_t; static constexpr const size_type npos = static_cast(-1); static_assert(!is_array_v, "character type of basic_string_view must not be an array"); static_assert(is_standard_layout_v, "character type of basic_string_view must be standard-layout"); static_assert(is_trivially_default_constructible_v, "character type of basic_string_view must be trivially default constructible"); static_assert(is_trivially_copyable_v, "character type of basic_string_view must be trivially copyable"); static_assert(is_same_v<_CharT, typename traits_type::char_type>, "traits_type::char_type must be the same type as CharT"); _CCCL_API constexpr basic_string_view() noexcept : __data_{} , __size_{} {} _CCCL_HIDE_FROM_ABI basic_string_view(const basic_string_view&) noexcept = default; _CCCL_HIDE_FROM_ABI basic_string_view& operator=(const basic_string_view&) noexcept = default; _CCCL_API constexpr basic_string_view(const _CharT* __s) noexcept : __data_{__s} , __size_{_Traits::length(__s)} {} basic_string_view(nullptr_t) = delete; _CCCL_API constexpr basic_string_view(const _CharT* __s, size_type __len) noexcept : __data_{__s} , __size_{__len} { // Allocations must fit in `difference_type` for pointer arithmetic to work. If `__len` exceeds it, the input // range could not have been valid. Most likely the caller underflowed some arithmetic and inadvertently // passed in a negative length. _CCCL_ASSERT(__len <= static_cast(numeric_limits::max()), "string_view::string_view(_CharT *, size_t): length does not fit in difference_type"); _CCCL_ASSERT(__len == 0 || __s != nullptr, "string_view::string_view(_CharT *, size_t): received nullptr"); } _CCCL_EXEC_CHECK_DISABLE _CCCL_TEMPLATE(class _It, class _End) _CCCL_REQUIRES(contiguous_iterator<_It> _CCCL_AND sized_sentinel_for<_End, _It> _CCCL_AND is_same_v, _CharT> _CCCL_AND(!is_convertible_v<_End, size_type>)) _CCCL_API constexpr basic_string_view(_It __begin, _End __end) : __data_{::cuda::std::to_address(__begin)} , __size_{static_cast(__end - __begin)} { _CCCL_ASSERT((__end - __begin) >= 0, "string_view::string_view(iterator, sentinel) received invalid range"); } #if _CCCL_HOSTED() _CCCL_TEMPLATE(class _Traits2, class _Alloc) _CCCL_REQUIRES(__cccl_basic_sv_is_std_to_cuda_std_char_traits<_Traits, _Traits2>) _CCCL_HOST_API constexpr basic_string_view(const ::std::basic_string<_CharT, _Traits2, _Alloc>& __sv) noexcept : __data_{__sv.data()} , __size_{__sv.size()} {} _CCCL_TEMPLATE(class _Traits2, class _Alloc) _CCCL_REQUIRES(is_same_v<_Traits, _Traits2>) _CCCL_HOST_API constexpr basic_string_view(const ::std::basic_string<_CharT, _Traits2, _Alloc>& __sv) noexcept : __data_{__sv.data()} , __size_{__sv.size()} {} #endif // _CCCL_HOSTED() #if __cpp_lib_string_view >= 201606L _CCCL_TEMPLATE(class _Traits2) _CCCL_REQUIRES(__cccl_basic_sv_is_std_to_cuda_std_char_traits<_Traits, _Traits2>) _CCCL_HOST_API constexpr basic_string_view(const ::std::basic_string_view<_CharT, _Traits2>& __s) noexcept : __data_{__s.data()} , __size_{__s.size()} {} _CCCL_TEMPLATE(class _Traits2) _CCCL_REQUIRES(is_same_v<_Traits, _Traits2>) _CCCL_HOST_API constexpr basic_string_view(const ::std::basic_string_view<_CharT, _Traits2>& __s) noexcept : __data_{__s.data()} , __size_{__s.size()} {} #endif // __cpp_lib_string_view >= 201606L // NOLINTBEGIN(bugprone-forwarding-reference-overload) _CCCL_TEMPLATE(class _Range) _CCCL_REQUIRES(__cccl_basic_sv_compatible_range<_Range, _CharT, _Traits>) _CCCL_API explicit constexpr basic_string_view(_Range&& __r) : __data_{::cuda::std::ranges::__data_cpo{}(__r)} , __size_{::cuda::std::ranges::__size_cpo{}(__r)} {} // NOLINTEND(bugprone-forwarding-reference-overload) // msvc has problems with constructing a string view from another string view using the from ranges constructor, // so we define the constructor ourselves #if _CCCL_COMPILER(MSVC) _CCCL_TEMPLATE(class _OtherTraits) _CCCL_REQUIRES((!is_same_v<_Traits, _OtherTraits>) ) _CCCL_API explicit constexpr basic_string_view(const basic_string_view<_CharT, _OtherTraits>& __other) : __data_{__other.data()} , __size_{__other.size()} {} #endif // _CCCL_COMPILER(MSVC) [[nodiscard]] _CCCL_API constexpr const_iterator begin() const noexcept { return const_iterator{__data_}; } [[nodiscard]] _CCCL_API constexpr const_iterator end() const noexcept { return const_iterator{__data_ + __size_}; } [[nodiscard]] _CCCL_API constexpr const_iterator cbegin() const noexcept { return const_iterator{__data_}; } [[nodiscard]] _CCCL_API constexpr const_iterator cend() const noexcept { return const_iterator{__data_ + __size_}; } [[nodiscard]] _CCCL_API constexpr const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator{cend()}; } [[nodiscard]] _CCCL_API constexpr const_reverse_iterator rend() const noexcept { return const_reverse_iterator{cbegin()}; } [[nodiscard]] _CCCL_API constexpr const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator{cend()}; } [[nodiscard]] _CCCL_API constexpr const_reverse_iterator crend() const noexcept { return const_reverse_iterator{cbegin()}; } [[nodiscard]] _CCCL_API constexpr size_type size() const noexcept { return __size_; } [[nodiscard]] _CCCL_API constexpr size_type length() const noexcept { return __size_; } // Workaround for cudafe++ < 13.1 + gcc < 13 replacing `numeric_limits` with // `numeric_limits, __common_type2_imp::type, void>::type>` template [[nodiscard]] _CCCL_API constexpr size_type max_size() const noexcept { return numeric_limits<_SizeType>::max() / sizeof(value_type); } [[nodiscard]] _CCCL_API constexpr bool empty() const noexcept { return __size_ == 0; } [[nodiscard]] _CCCL_API constexpr const_reference operator[](size_type __pos) const noexcept { _CCCL_ASSERT(__pos < __size_, "string_view[] index out of bounds"); return __data_[__pos]; } [[nodiscard]] _CCCL_API constexpr const_reference at(size_type __pos) const { if (__pos >= __size_) { _CCCL_THROW(::std::out_of_range, "string_view::at"); } return __data_[__pos]; } [[nodiscard]] _CCCL_API constexpr const_reference front() const noexcept { _CCCL_ASSERT(__size_ > 0, "string_view::front(): string is empty"); return __data_[0]; } [[nodiscard]] _CCCL_API constexpr const_reference back() const noexcept { _CCCL_ASSERT(__size_ > 0, "string_view::back(): string is empty"); return __data_[__size_ - 1]; } [[nodiscard]] _CCCL_API constexpr const_pointer data() const noexcept { return __data_; } _CCCL_API constexpr void remove_prefix(size_type __n) noexcept { _CCCL_ASSERT(__n <= __size_, "remove_prefix() can't remove more than size()"); __data_ += __n; __size_ -= __n; } _CCCL_API constexpr void remove_suffix(size_type __n) noexcept { _CCCL_ASSERT(__n <= __size_, "remove_suffix() can't remove more than size()"); __size_ -= __n; } _CCCL_API constexpr void swap(basic_string_view& __other) noexcept { const value_type* __p = __data_; __data_ = __other.__data_; __other.__data_ = __p; size_type __sz = __size_; __size_ = __other.__size_; __other.__size_ = __sz; } _CCCL_API constexpr size_type copy(_CharT* __s, size_type __n, size_type __pos = 0) const { if (__pos > __size_) { _CCCL_THROW(::std::out_of_range, "string_view::copy"); } const auto __rlen = ::cuda::std::min(__n, __size_ - __pos); _Traits::copy(__s, __data_ + __pos, __rlen); return __rlen; } [[nodiscard]] _CCCL_API constexpr basic_string_view substr(size_type __pos = 0, size_type __n = npos) const { // Use the `__assume_valid` form of the constructor to avoid an unnecessary check. Any substring of a view is a // valid view. In particular, `size()` is known to be smaller than `numeric_limits::max()`, so the // new size is also smaller. See also https://github.com/llvm/llvm-project/issues/91634. if (__pos > __size_) { _CCCL_THROW(::std::out_of_range, "string_view::substr"); } return basic_string_view{__assume_valid{}, __data_ + __pos, ::cuda::std::min(__n, __size_ - __pos)}; } // compare [[nodiscard]] _CCCL_API constexpr int compare(basic_string_view __sv) const noexcept { const auto __rlen = ::cuda::std::min(__size_, __sv.__size_); int __retval = _Traits::compare(__data_, __sv.__data_, __rlen); if (__retval == 0) // first __rlen chars matched { __retval = (__size_ == __sv.__size_) ? 0 : ((__size_ < __sv.__size_) ? -1 : 1); } return __retval; } [[nodiscard]] _CCCL_API constexpr int compare(size_type __pos1, size_type __n1, basic_string_view __sv) const { return substr(__pos1, __n1).compare(__sv); } [[nodiscard]] _CCCL_API constexpr int compare(size_type __pos1, size_type __n1, basic_string_view __sv, size_type __pos2, size_type __n2) const { return substr(__pos1, __n1).compare(__sv.substr(__pos2, __n2)); } [[nodiscard]] _CCCL_API constexpr int compare(const _CharT* __s) const noexcept { return compare(basic_string_view{__s}); } [[nodiscard]] _CCCL_API constexpr int compare(size_type __pos1, size_type __n1, const _CharT* __s) const { return substr(__pos1, __n1).compare(basic_string_view{__s}); } [[nodiscard]] _CCCL_API constexpr int compare(size_type __pos1, size_type __n1, const _CharT* __s, size_type __n2) const { return substr(__pos1, __n1).compare(basic_string_view{__s, __n2}); } // find [[nodiscard]] _CCCL_API constexpr size_type find(basic_string_view __s, size_type __pos = 0) const noexcept { _CCCL_ASSERT(__s.__size_ == 0 || __s.__data_ != nullptr, "string_view::find(): received nullptr"); return ::cuda::std::__cccl_str_find( __data_, __size_, __s.__data_, __pos, __s.__size_); } [[nodiscard]] _CCCL_API constexpr size_type find(_CharT __c, size_type __pos = 0) const noexcept { return ::cuda::std::__cccl_str_find(__data_, __size_, __c, __pos); } [[nodiscard]] _CCCL_API constexpr size_type find(const _CharT* __s, size_type __pos, size_type __n) const noexcept { _CCCL_ASSERT(__n == 0 || __s != nullptr, "string_view::find(): received nullptr"); return ::cuda::std::__cccl_str_find(__data_, __size_, __s, __pos, __n); } [[nodiscard]] _CCCL_API constexpr size_type find(const _CharT* __s, size_type __pos = 0) const noexcept { _CCCL_ASSERT(__s != nullptr, "string_view::find(): received nullptr"); return ::cuda::std::__cccl_str_find( __data_, __size_, __s, __pos, traits_type::length(__s)); } // rfind [[nodiscard]] _CCCL_API constexpr size_type rfind(basic_string_view __s, size_type __pos = npos) const noexcept { _CCCL_ASSERT(__s.__size_ == 0 || __s.__data_ != nullptr, "string_view::find(): received nullptr"); return ::cuda::std::__cccl_str_rfind( __data_, __size_, __s.__data_, __pos, __s.__size_); } [[nodiscard]] _CCCL_API constexpr size_type rfind(_CharT __c, size_type __pos = npos) const noexcept { return ::cuda::std::__cccl_str_rfind(__data_, __size_, __c, __pos); } [[nodiscard]] _CCCL_API constexpr size_type rfind(const _CharT* __s, size_type __pos, size_type __n) const noexcept { _CCCL_ASSERT(__n == 0 || __s != nullptr, "string_view::rfind(): received nullptr"); return ::cuda::std::__cccl_str_rfind(__data_, __size_, __s, __pos, __n); } [[nodiscard]] _CCCL_API constexpr size_type rfind(const _CharT* __s, size_type __pos = npos) const noexcept { _CCCL_ASSERT(__s != nullptr, "string_view::rfind(): received nullptr"); return ::cuda::std::__cccl_str_rfind( __data_, __size_, __s, __pos, traits_type::length(__s)); } // find_first_of [[nodiscard]] _CCCL_API constexpr size_type find_first_of(basic_string_view __s, size_type __pos = 0) const noexcept { _CCCL_ASSERT(__s.__size_ == 0 || __s.__data_ != nullptr, "string_view::find_first_of(): received nullptr"); return ::cuda::std::__cccl_str_find_first_of( __data_, __size_, __s.__data_, __pos, __s.__size_); } [[nodiscard]] _CCCL_API constexpr size_type find_first_of(_CharT __c, size_type __pos = 0) const noexcept { return find(__c, __pos); } [[nodiscard]] _CCCL_API constexpr size_type find_first_of(const _CharT* __s, size_type __pos, size_type __n) const noexcept { _CCCL_ASSERT(__n == 0 || __s != nullptr, "string_view::find_first_of(): received nullptr"); return ::cuda::std::__cccl_str_find_first_of( __data_, __size_, __s, __pos, __n); } [[nodiscard]] _CCCL_API constexpr size_type find_first_of(const _CharT* __s, size_type __pos = 0) const noexcept { _CCCL_ASSERT(__s != nullptr, "string_view::find_first_of(): received nullptr"); return ::cuda::std::__cccl_str_find_first_of( __data_, __size_, __s, __pos, traits_type::length(__s)); } // find_last_of [[nodiscard]] _CCCL_API constexpr size_type find_last_of(basic_string_view __s, size_type __pos = npos) const noexcept { _CCCL_ASSERT(__s.__size_ == 0 || __s.__data_ != nullptr, "string_view::find_last_of(): received nullptr"); return ::cuda::std::__cccl_str_find_last_of( __data_, __size_, __s.__data_, __pos, __s.__size_); } [[nodiscard]] _CCCL_API constexpr size_type find_last_of(_CharT __c, size_type __pos = npos) const noexcept { return rfind(__c, __pos); } [[nodiscard]] _CCCL_API constexpr size_type find_last_of(const _CharT* __s, size_type __pos, size_type __n) const noexcept { _CCCL_ASSERT(__n == 0 || __s != nullptr, "string_view::find_last_of(): received nullptr"); return ::cuda::std::__cccl_str_find_last_of( __data_, __size_, __s, __pos, __n); } [[nodiscard]] _CCCL_API constexpr size_type find_last_of(const _CharT* __s, size_type __pos = npos) const noexcept { _CCCL_ASSERT(__s != nullptr, "string_view::find_last_of(): received nullptr"); return ::cuda::std::__cccl_str_find_last_of( __data_, __size_, __s, __pos, traits_type::length(__s)); } // find_first_not_of [[nodiscard]] _CCCL_API constexpr size_type find_first_not_of(basic_string_view __s, size_type __pos = 0) const noexcept { _CCCL_ASSERT(__s.__size_ == 0 || __s.__data_ != nullptr, "string_view::find_first_not_of(): received nullptr"); return ::cuda::std::__cccl_str_find_first_not_of( __data_, __size_, __s.__data_, __pos, __s.__size_); } [[nodiscard]] _CCCL_API constexpr size_type find_first_not_of(_CharT __c, size_type __pos = 0) const noexcept { return ::cuda::std::__cccl_str_find_first_not_of( __data_, __size_, __c, __pos); } [[nodiscard]] _CCCL_API constexpr size_type find_first_not_of(const _CharT* __s, size_type __pos, size_type __n) const noexcept { _CCCL_ASSERT(__n == 0 || __s != nullptr, "string_view::find_first_not_of(): received nullptr"); return ::cuda::std::__cccl_str_find_first_not_of( __data_, __size_, __s, __pos, __n); } [[nodiscard]] _CCCL_API constexpr size_type find_first_not_of(const _CharT* __s, size_type __pos = 0) const noexcept { _CCCL_ASSERT(__s != nullptr, "string_view::find_first_not_of(): received nullptr"); return ::cuda::std::__cccl_str_find_first_not_of( __data_, __size_, __s, __pos, traits_type::length(__s)); } // find_last_not_of [[nodiscard]] _CCCL_API constexpr size_type find_last_not_of(basic_string_view __s, size_type __pos = npos) const noexcept { _CCCL_ASSERT(__s.__size_ == 0 || __s.__data_ != nullptr, "string_view::find_last_not_of(): received nullptr"); return ::cuda::std::__cccl_str_find_last_not_of( __data_, __size_, __s.__data_, __pos, __s.__size_); } [[nodiscard]] _CCCL_API constexpr size_type find_last_not_of(_CharT __c, size_type __pos = npos) const noexcept { return ::cuda::std::__cccl_str_find_last_not_of( __data_, __size_, __c, __pos); } [[nodiscard]] _CCCL_API constexpr size_type find_last_not_of(const _CharT* __s, size_type __pos, size_type __n) const noexcept { _CCCL_ASSERT(__n == 0 || __s != nullptr, "string_view::find_last_not_of(): received nullptr"); return ::cuda::std::__cccl_str_find_last_not_of( __data_, __size_, __s, __pos, __n); } [[nodiscard]] _CCCL_API constexpr size_type find_last_not_of(const _CharT* __s, size_type __pos = npos) const noexcept { _CCCL_ASSERT(__s != nullptr, "string_view::find_last_not_of(): received nullptr"); return ::cuda::std::__cccl_str_find_last_not_of( __data_, __size_, __s, __pos, traits_type::length(__s)); } // starts_with [[nodiscard]] _CCCL_API constexpr bool starts_with(basic_string_view __s) const noexcept { return (__size_ >= __s.__size_) && compare(0, __s.__size_, __s) == 0; } [[nodiscard]] _CCCL_API constexpr bool starts_with(value_type __c) const noexcept { return (__size_ > 0) && _Traits::eq(front(), __c); } [[nodiscard]] _CCCL_API constexpr bool starts_with(const value_type* __s) const noexcept { return starts_with(basic_string_view{__s}); } // ends_with [[nodiscard]] _CCCL_API constexpr bool ends_with(basic_string_view __s) const noexcept { return (__size_ >= __s.__size_) && compare(__size_ - __s.__size_, npos, __s) == 0; } [[nodiscard]] _CCCL_API constexpr bool ends_with(value_type __c) const noexcept { return (__size_ > 0) && _Traits::eq(back(), __c); } [[nodiscard]] _CCCL_API constexpr bool ends_with(const value_type* __s) const noexcept { return ends_with(basic_string_view{__s}); } // contains [[nodiscard]] _CCCL_API constexpr bool contains(basic_string_view __sv) const noexcept { return find(__sv) != npos; } [[nodiscard]] _CCCL_API constexpr bool contains(value_type __c) const noexcept { return find(__c) != npos; } [[nodiscard]] _CCCL_API constexpr bool contains(const value_type* __s) const noexcept { return find(__s) != npos; } // The dummy default template parameters are used to work around a MSVC issue with mangling, see VSO-409326 for // details. This applies to the other sufficient overloads below for the other comparison operators. // operator == [[nodiscard]] _CCCL_API friend constexpr bool operator==(basic_string_view __lhs, basic_string_view __rhs) noexcept { if (__lhs.__size_ != __rhs.__size_) { return false; } return __lhs.compare(__rhs) == 0; } template [[nodiscard]] _CCCL_API friend constexpr bool operator==(basic_string_view __lhs, type_identity_t __rhs) noexcept { if (__lhs.__size_ != __rhs.__size_) { return false; } return __lhs.compare(__rhs) == 0; } template [[nodiscard]] _CCCL_API friend constexpr bool operator==(type_identity_t __lhs, basic_string_view __rhs) noexcept { return __lhs == __rhs; } // operator != [[nodiscard]] _CCCL_API friend constexpr bool operator!=(basic_string_view __lhs, basic_string_view __rhs) noexcept { return !(__lhs == __rhs); } template [[nodiscard]] _CCCL_API friend constexpr bool operator!=(basic_string_view __lhs, type_identity_t __rhs) noexcept { return !(__lhs == __rhs); } template [[nodiscard]] _CCCL_API friend constexpr bool operator!=(type_identity_t __lhs, basic_string_view __rhs) noexcept { return !(__lhs == __rhs); } // operator < [[nodiscard]] _CCCL_API friend constexpr bool operator<(basic_string_view __lhs, basic_string_view __rhs) noexcept { return __lhs.compare(__rhs) < 0; } template [[nodiscard]] _CCCL_API friend constexpr bool operator<(basic_string_view __lhs, type_identity_t __rhs) noexcept { return __lhs.compare(__rhs) < 0; } template [[nodiscard]] _CCCL_API friend constexpr bool operator<(type_identity_t __lhs, basic_string_view __rhs) noexcept { return __lhs.compare(__rhs) < 0; } // operator > [[nodiscard]] _CCCL_API friend constexpr bool operator>(basic_string_view __lhs, basic_string_view __rhs) noexcept { return __lhs.compare(__rhs) > 0; } template [[nodiscard]] _CCCL_API friend constexpr bool operator>(basic_string_view __lhs, type_identity_t __rhs) noexcept { return __lhs.compare(__rhs) > 0; } template [[nodiscard]] _CCCL_API friend constexpr bool operator>(type_identity_t __lhs, basic_string_view __rhs) noexcept { return __lhs.compare(__rhs) > 0; } // operator <= [[nodiscard]] _CCCL_API friend constexpr bool operator<=(basic_string_view __lhs, basic_string_view __rhs) noexcept { return __lhs.compare(__rhs) <= 0; } template [[nodiscard]] _CCCL_API friend constexpr bool operator<=(basic_string_view __lhs, type_identity_t __rhs) noexcept { return __lhs.compare(__rhs) <= 0; } template [[nodiscard]] _CCCL_API friend constexpr bool operator<=(type_identity_t __lhs, basic_string_view __rhs) noexcept { return __lhs.compare(__rhs) <= 0; } // operator >= [[nodiscard]] _CCCL_API friend constexpr bool operator>=(basic_string_view __lhs, basic_string_view __rhs) noexcept { return __lhs.compare(__rhs) >= 0; } template [[nodiscard]] _CCCL_API friend constexpr bool operator>=(basic_string_view __lhs, type_identity_t __rhs) noexcept { return __lhs.compare(__rhs) >= 0; } template [[nodiscard]] _CCCL_API friend constexpr bool operator>=(type_identity_t __lhs, basic_string_view __rhs) noexcept { return __lhs.compare(__rhs) >= 0; } #if __cpp_lib_string_view >= 201606L _CCCL_TEMPLATE(class _Traits2 = _Traits) _CCCL_REQUIRES(is_same_v<_Traits2, char_traits<_CharT>>) _CCCL_HOST_API constexpr operator ::std::basic_string_view<_CharT>() const noexcept { return ::std::basic_string_view<_CharT>{__data_, __size_}; } _CCCL_HOST_API constexpr operator ::std::basic_string_view<_CharT, _Traits>() const noexcept { return ::std::basic_string_view<_CharT, _Traits>{__data_, __size_}; } #endif // ^^^ __cpp_lib_string_view >= 201606L ^^^ private: enum class __assume_valid { }; // This is the same as the pointer and length constructor, but without the additional hardening checks. It is intended // for use within the class, when the class invariants already guarantee the resulting object is valid. The compiler // usually cannot eliminate the redundant checks because it does not know class invariants. _CCCL_API constexpr basic_string_view(__assume_valid, const _CharT* __s, size_type __len) noexcept : __data_{__s} , __size_{__len} {} const value_type* __data_; size_type __size_; }; _CCCL_CTAD_SUPPORTED_FOR_TYPE(basic_string_view); _CCCL_TEMPLATE(class _It, class _End) _CCCL_REQUIRES(contiguous_iterator<_It> _CCCL_AND sized_sentinel_for<_End, _It>) _CCCL_DEDUCTION_GUIDE_ATTRIBUTES basic_string_view(_It, _End) -> basic_string_view>; _CCCL_TEMPLATE(class _Range) _CCCL_REQUIRES(::cuda::std::ranges::contiguous_range<_Range>) _CCCL_DEDUCTION_GUIDE_ATTRIBUTES basic_string_view(_Range&&) -> basic_string_view<::cuda::std::ranges::range_value_t<_Range>>; #if _CCCL_HOSTED() template basic_string_view(::std::basic_string<_CharT, ::std::char_traits<_CharT>, _Alloc>) -> basic_string_view<_CharT>; template basic_string_view(::std::basic_string<_CharT, _Traits, _Alloc>) -> basic_string_view<_CharT, _Traits>; #endif // _CCCL_HOSTED() #if __cpp_lib_string_view >= 201606L template basic_string_view(::std::basic_string_view<_CharT>) -> basic_string_view<_CharT>; template basic_string_view(::std::basic_string_view<_CharT, _Traits>) -> basic_string_view<_CharT, _Traits>; #endif // __cpp_lib_string_view >= 201606L // operator << #if _CCCL_HOSTED() template _CCCL_HOST_API ::std::basic_ostream<_CharT>& operator<<(::std::basic_ostream<_CharT>& __os, basic_string_view<_CharT> __str) { # if __cpp_lib_string_view >= 201606L return __os << ::std::basic_string_view<_CharT, ::std::char_traits<_CharT>>{__str}; # else // ^^^ __cpp_lib_string_view >= 201606L ^^^ / vvv __cpp_lib_string_view < 201606L vvv return __os << ::std::basic_string<_CharT, ::std::char_traits<_CharT>, ::std::allocator<_CharT>>{__str.data(), __str.size()}; # endif // ^^^ __cpp_lib_string_view < 201606L ^^^ } template _CCCL_HOST_API ::std::basic_ostream<_CharT, _Traits>& operator<<(::std::basic_ostream<_CharT, _Traits>& __os, basic_string_view<_CharT, _Traits> __str) { # if __cpp_lib_string_view >= 201606L return __os << ::std::basic_string_view<_CharT, _Traits>{__str}; # else // ^^^ __cpp_lib_string_view >= 201606L ^^^ / vvv __cpp_lib_string_view < 201606L vvv return __os << ::std::basic_string<_CharT, _Traits, ::std::allocator<_CharT>>{__str.data(), __str.size()}; # endif // ^^^ __cpp_lib_string_view < 201606L ^^^ } #endif // _CCCL_HOSTED() // literals _CCCL_DIAG_PUSH _CCCL_DIAG_SUPPRESS_GCC("-Wliteral-suffix") _CCCL_DIAG_SUPPRESS_CLANG("-Wuser-defined-literals") _CCCL_DIAG_SUPPRESS_MSVC(4455) inline namespace literals { inline namespace string_view_literals { _CCCL_API constexpr basic_string_view operator""sv(const char* __str, size_t __len) noexcept { return basic_string_view{__str, __len}; } #if _CCCL_HAS_WCHAR_T() _CCCL_API constexpr basic_string_view operator""sv(const wchar_t* __str, size_t __len) noexcept { return basic_string_view{__str, __len}; } #endif // _CCCL_HAS_WCHAR_T() #if _CCCL_HAS_CHAR8_T() _CCCL_API constexpr basic_string_view operator""sv(const char8_t* __str, size_t __len) noexcept { return basic_string_view{__str, __len}; } #endif // _CCCL_HAS_CHAR8_T() _CCCL_API constexpr basic_string_view operator""sv(const char16_t* __str, size_t __len) noexcept { return basic_string_view{__str, __len}; } _CCCL_API constexpr basic_string_view operator""sv(const char32_t* __str, size_t __len) noexcept { return basic_string_view{__str, __len}; } } // namespace string_view_literals } // namespace literals _CCCL_DIAG_POP _CCCL_END_NAMESPACE_CUDA_STD _CCCL_BEGIN_NAMESPACE_CUDA_STD_RANGES template inline constexpr bool enable_view<::cuda::std::basic_string_view<_CharT, _Traits>> = true; template inline constexpr bool enable_borrowed_range<::cuda::std::basic_string_view<_CharT, _Traits>> = true; _CCCL_END_NAMESPACE_CUDA_STD_RANGES #include #endif // _CUDA_STD_STRING_VIEW