Skip to content

Commit daf85db

Browse files
authored
Fix string_view construction from std::string_view (NVIDIA#6291) (NVIDIA#6301)
1 parent a9c8c78 commit daf85db

File tree

3 files changed

+141
-10
lines changed

3 files changed

+141
-10
lines changed

libcudacxx/include/cuda/std/__fwd/char_traits.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@ template <>
4242
struct char_traits<wchar_t>;
4343
#endif // _CCCL_HAS_WCHAR_T()
4444

45+
template <class _Tp>
46+
inline constexpr bool __is_cuda_std_char_traits_v = false;
47+
template <class _Tp>
48+
inline constexpr bool __is_cuda_std_char_traits_v<char_traits<_Tp>> = true;
49+
4550
_LIBCUDACXX_END_NAMESPACE_STD
4651

4752
#include <cuda/std/__cccl/epilogue.h>

libcudacxx/include/cuda/std/string_view

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,13 @@ template <class _CharT, class _Traits, class _Alloc>
8484
inline constexpr bool __cccl_is_std_string_v<::std::basic_string<_CharT, _Traits, _Alloc>> = true;
8585
#endif // !_CCCL_COMPILER(NVRTC)
8686

87+
template <class _Tp>
88+
inline constexpr bool __is_std_char_traits_v = false;
89+
#if !_CCCL_COMPILER(NVRTC)
90+
template <class _Tp>
91+
inline constexpr bool __is_std_char_traits_v<::std::char_traits<_Tp>> = true;
92+
#endif // !_CCCL_COMPILER(NVRTC)
93+
8794
template <class _Tp>
8895
inline constexpr bool __cccl_is_std_string_view_v = false;
8996
#if __cpp_lib_string_view >= 201606L
@@ -134,6 +141,13 @@ _CCCL_CONCEPT __cccl_basic_sv_compatible_range = _CCCL_REQUIRES_EXPR((_Range, _C
134141
|| __cccl_basic_sv_compatible_range_check_traits_std_ext<_Range, _CharT, _Traits>) )) //
135142
);
136143

144+
template <class _Traits, class _HostTraits>
145+
_CCCL_CONCEPT __cccl_basic_sv_is_std_to_cuda_std_char_traits = _CCCL_REQUIRES_EXPR((_Traits, _HostTraits)) //
146+
( //
147+
requires(__is_cuda_std_char_traits_v<_Traits>), //
148+
requires(__is_std_char_traits_v<_HostTraits>) //
149+
);
150+
137151
template <class _CharT, class _Traits>
138152
class _CCCL_TYPE_VISIBILITY_DEFAULT basic_string_view
139153
{
@@ -201,30 +215,32 @@ public:
201215
}
202216

203217
#if !_CCCL_COMPILER(NVRTC)
204-
_CCCL_TEMPLATE(class _Traits2 = _Traits, class _Alloc)
205-
_CCCL_REQUIRES(is_same_v<_Traits2, char_traits<_CharT>>)
206-
_CCCL_HOST_API constexpr basic_string_view(
207-
const ::std::basic_string<_CharT, ::std::char_traits<_CharT>, _Alloc>& __sv) noexcept
218+
_CCCL_TEMPLATE(class _Traits2, class _Alloc)
219+
_CCCL_REQUIRES(__cccl_basic_sv_is_std_to_cuda_std_char_traits<_Traits, _Traits2>)
220+
_CCCL_HOST_API constexpr basic_string_view(const ::std::basic_string<_CharT, _Traits2, _Alloc>& __sv) noexcept
208221
: __data_{__sv.data()}
209222
, __size_{__sv.size()}
210223
{}
211224

212-
template <class _Alloc>
213-
_CCCL_HOST_API constexpr basic_string_view(const ::std::basic_string<_CharT, _Traits, _Alloc>& __sv) noexcept
225+
_CCCL_TEMPLATE(class _Traits2, class _Alloc)
226+
_CCCL_REQUIRES(is_same_v<_Traits, _Traits2>)
227+
_CCCL_HOST_API constexpr basic_string_view(const ::std::basic_string<_CharT, _Traits2, _Alloc>& __sv) noexcept
214228
: __data_{__sv.data()}
215229
, __size_{__sv.size()}
216230
{}
217231
#endif // !_CCCL_COMPILER(NVRTC)
218232

219233
#if __cpp_lib_string_view >= 201606L
220-
_CCCL_TEMPLATE(class _Traits2 = _Traits)
221-
_CCCL_REQUIRES(is_same_v<_Traits2, char_traits<_CharT>>)
222-
_CCCL_HOST_API constexpr basic_string_view(::std::basic_string_view<_CharT> __s) noexcept
234+
_CCCL_TEMPLATE(class _Traits2)
235+
_CCCL_REQUIRES(__cccl_basic_sv_is_std_to_cuda_std_char_traits<_Traits, _Traits2>)
236+
_CCCL_HOST_API constexpr basic_string_view(const ::std::basic_string_view<_CharT, _Traits2>& __s) noexcept
223237
: __data_{__s.data()}
224238
, __size_{__s.size()}
225239
{}
226240

227-
_CCCL_HOST_API constexpr basic_string_view(::std::basic_string_view<_CharT, _Traits> __s) noexcept
241+
_CCCL_TEMPLATE(class _Traits2)
242+
_CCCL_REQUIRES(is_same_v<_Traits, _Traits2>)
243+
_CCCL_HOST_API constexpr basic_string_view(const ::std::basic_string_view<_CharT, _Traits2>& __s) noexcept
228244
: __data_{__s.data()}
229245
, __size_{__s.size()}
230246
{}
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the libcu++ Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
// SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES.
7+
//
8+
//===----------------------------------------------------------------------===//
9+
10+
// <cuda/std/string_view>
11+
12+
// UNSUPPORTED: nvrtc
13+
14+
#include <cuda/std/cassert>
15+
#include <cuda/std/string_view>
16+
#include <cuda/std/type_traits>
17+
18+
#include <string>
19+
20+
#include "literal.h"
21+
22+
enum class MyChar : char
23+
{
24+
};
25+
26+
template <>
27+
struct std::char_traits<MyChar>
28+
{};
29+
30+
template <>
31+
struct cuda::std::char_traits<MyChar>
32+
{
33+
using base = cuda::std::char_traits<char>;
34+
35+
using char_type = MyChar;
36+
using int_type = typename base::int_type;
37+
38+
__host__ __device__ static constexpr void assign(char_type& __lhs, const char_type& __rhs) noexcept
39+
{
40+
__lhs = __rhs;
41+
}
42+
43+
[[nodiscard]] __host__ __device__ static constexpr bool eq(char_type __lhs, char_type __rhs) noexcept
44+
{
45+
return __lhs == __rhs;
46+
}
47+
48+
[[nodiscard]] __host__ __device__ static constexpr bool lt(char_type __lhs, char_type __rhs) noexcept
49+
{
50+
return static_cast<unsigned char>(__lhs) < static_cast<unsigned char>(__rhs);
51+
}
52+
53+
[[nodiscard]] __host__ __device__ static constexpr int
54+
compare(const char_type* __lhs, const char_type* __rhs, size_t __count) noexcept
55+
{
56+
return ::cuda::std::__cccl_memcmp(__lhs, __rhs, __count);
57+
}
58+
59+
[[nodiscard]] __host__ __device__ inline static size_t constexpr length(const char_type* __s) noexcept
60+
{
61+
return ::cuda::std::__cccl_strlen(__s);
62+
}
63+
64+
[[nodiscard]] __host__ __device__ static constexpr const char_type*
65+
find(const char_type* __s, size_t __n, const char_type& __a) noexcept
66+
{
67+
return ::cuda::std::__cccl_memchr<const char_type>(__s, __a, __n);
68+
}
69+
70+
__host__ __device__ static constexpr char_type* move(char_type* __s1, const char_type* __s2, size_t __n) noexcept
71+
{
72+
return ::cuda::std::__cccl_memmove(__s1, __s2, __n);
73+
}
74+
75+
__host__ __device__ static constexpr char_type* copy(char_type* __s1, const char_type* __s2, size_t __n) noexcept
76+
{
77+
return ::cuda::std::__cccl_memcpy(__s1, __s2, __n);
78+
}
79+
80+
__host__ __device__ static constexpr char_type* assign(char_type* __s, size_t __n, char_type __a) noexcept
81+
{
82+
return ::cuda::std::__cccl_memset(__s, __a, __n);
83+
}
84+
85+
[[nodiscard]] __host__ __device__ static constexpr char_type to_char_type(int_type __c) noexcept
86+
{
87+
return char_type(__c);
88+
}
89+
90+
[[nodiscard]] __host__ __device__ static constexpr int_type to_int_type(char_type __c) noexcept
91+
{
92+
return int_type(static_cast<unsigned char>(__c));
93+
}
94+
95+
[[nodiscard]] __host__ __device__ static constexpr bool eq_int_type(int_type __lhs, int_type __rhs) noexcept
96+
{
97+
return __lhs == __rhs;
98+
}
99+
};
100+
101+
bool test()
102+
{
103+
[[maybe_unused]] cuda::std::basic_string_view<MyChar> str{reinterpret_cast<const MyChar*>("test")};
104+
return true;
105+
}
106+
107+
int main(int, char**)
108+
{
109+
return 0;
110+
}

0 commit comments

Comments
 (0)