1c16b13ebSJoe Loser //===----------------------------------------------------------------------===//
2c16b13ebSJoe Loser //
3c16b13ebSJoe Loser // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4c16b13ebSJoe Loser // See https://llvm.org/LICENSE.txt for license information.
5c16b13ebSJoe Loser // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6c16b13ebSJoe Loser //
7c16b13ebSJoe Loser //===----------------------------------------------------------------------===//
8c16b13ebSJoe Loser // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
9c16b13ebSJoe Loser // UNSUPPORTED: libcpp-no-concepts
10c16b13ebSJoe Loser // UNSUPPORTED: libcpp-has-no-incomplete-ranges
11c16b13ebSJoe Loser 
12c16b13ebSJoe Loser // <string_view>
13c16b13ebSJoe Loser 
14c16b13ebSJoe Loser //  template <class Range>
15c16b13ebSJoe Loser //  constexpr basic_string_view(Range&& range);
16c16b13ebSJoe Loser 
17c16b13ebSJoe Loser #include <string_view>
18c16b13ebSJoe Loser #include <array>
19c16b13ebSJoe Loser #include <cassert>
20c16b13ebSJoe Loser #include <iterator>
21c16b13ebSJoe Loser #include <ranges>
22c16b13ebSJoe Loser #include <type_traits>
23c16b13ebSJoe Loser #include <vector>
24c16b13ebSJoe Loser 
25c16b13ebSJoe Loser #include "constexpr_char_traits.h"
26c16b13ebSJoe Loser #include "make_string.h"
27c16b13ebSJoe Loser #include "test_iterators.h"
28c16b13ebSJoe Loser #include "test_range.h"
29c16b13ebSJoe Loser 
30c16b13ebSJoe Loser template<class CharT>
31c16b13ebSJoe Loser constexpr void test() {
32c16b13ebSJoe Loser   auto data = MAKE_STRING_VIEW(CharT, "test");
33c16b13ebSJoe Loser   std::array<CharT, 4> arr;
34c16b13ebSJoe Loser   for(int i = 0; i < 4; ++i) {
35c16b13ebSJoe Loser     arr[i] = data[i];
36c16b13ebSJoe Loser   }
37c16b13ebSJoe Loser   auto sv = std::basic_string_view<CharT>(arr);
38c16b13ebSJoe Loser 
39c16b13ebSJoe Loser   ASSERT_SAME_TYPE(decltype(sv), std::basic_string_view<CharT>);
40c16b13ebSJoe Loser   assert(sv.size() == arr.size());
41c16b13ebSJoe Loser   assert(sv.data() == arr.data());
42c16b13ebSJoe Loser }
43c16b13ebSJoe Loser 
44c16b13ebSJoe Loser constexpr bool test() {
45c16b13ebSJoe Loser   test<char>();
46c16b13ebSJoe Loser #ifndef TEST_HAS_NO_WIDE_CHARACTERS
47c16b13ebSJoe Loser   test<wchar_t>();
48c16b13ebSJoe Loser #endif
49c16b13ebSJoe Loser   test<char8_t>();
50c16b13ebSJoe Loser   test<char16_t>();
51c16b13ebSJoe Loser   test<char32_t>();
52c16b13ebSJoe Loser 
53c16b13ebSJoe Loser   {
54c16b13ebSJoe Loser     struct NonConstConversionOperator {
55c16b13ebSJoe Loser       const char* data_ = "test";
56c16b13ebSJoe Loser       constexpr const char* begin() const { return data_; }
57c16b13ebSJoe Loser       constexpr const char* end() const { return data_ + 4; }
58c16b13ebSJoe Loser       constexpr operator std::basic_string_view<char>() { return "NonConstConversionOp"; }
59c16b13ebSJoe Loser     };
60c16b13ebSJoe Loser 
61c16b13ebSJoe Loser     NonConstConversionOperator nc;
62c16b13ebSJoe Loser     std::string_view sv = nc;
63c16b13ebSJoe Loser     assert(sv == "NonConstConversionOp");
64c16b13ebSJoe Loser     static_assert(!std::is_constructible_v<std::string_view,
65c16b13ebSJoe Loser                                            const NonConstConversionOperator&>); // conversion operator is non-const
66c16b13ebSJoe Loser   }
67c16b13ebSJoe Loser 
68c16b13ebSJoe Loser   {
69c16b13ebSJoe Loser     struct ConstConversionOperator {
70c16b13ebSJoe Loser       const char* data_ = "test";
71c16b13ebSJoe Loser       constexpr const char* begin() const { return data_; }
72c16b13ebSJoe Loser       constexpr const char* end() const { return data_ + 4; }
73c16b13ebSJoe Loser       constexpr operator std::basic_string_view<char>() const { return "ConstConversionOp"; }
74c16b13ebSJoe Loser     };
75c16b13ebSJoe Loser     ConstConversionOperator cv;
76c16b13ebSJoe Loser     std::basic_string_view<char> sv = cv;
77c16b13ebSJoe Loser     assert(sv == "ConstConversionOp");
78c16b13ebSJoe Loser   }
79c16b13ebSJoe Loser 
80c16b13ebSJoe Loser   struct DeletedConversionOperator {
81c16b13ebSJoe Loser     const char* data_ = "test";
82c16b13ebSJoe Loser     constexpr const char* begin() const { return data_; }
83c16b13ebSJoe Loser     constexpr const char* end() const { return data_ + 4; }
84c16b13ebSJoe Loser     operator std::basic_string_view<char>() = delete;
85c16b13ebSJoe Loser   };
86c16b13ebSJoe Loser 
87c16b13ebSJoe Loser   struct DeletedConstConversionOperator {
88c16b13ebSJoe Loser     const char* data_ = "test";
89c16b13ebSJoe Loser     constexpr const char* begin() const { return data_; }
90c16b13ebSJoe Loser     constexpr const char* end() const { return data_ + 4; }
91c16b13ebSJoe Loser     operator std::basic_string_view<char>() const = delete;
92c16b13ebSJoe Loser   };
93c16b13ebSJoe Loser 
94c16b13ebSJoe Loser   static_assert(std::is_constructible_v<std::string_view, DeletedConversionOperator>);
95c16b13ebSJoe Loser   static_assert(std::is_constructible_v<std::string_view, const DeletedConversionOperator>);
96c16b13ebSJoe Loser   static_assert(std::is_constructible_v<std::string_view, DeletedConstConversionOperator>);
97c16b13ebSJoe Loser   static_assert(std::is_constructible_v<std::string_view, const DeletedConstConversionOperator>);
98c16b13ebSJoe Loser 
99c16b13ebSJoe Loser   // Test that we're not trying to use the type's conversion operator to string_view in the constructor.
100c16b13ebSJoe Loser   {
101c16b13ebSJoe Loser     const DeletedConversionOperator d;
102c16b13ebSJoe Loser     std::basic_string_view<char> csv = d;
103c16b13ebSJoe Loser     assert(csv == "test");
104c16b13ebSJoe Loser   }
105c16b13ebSJoe Loser 
106c16b13ebSJoe Loser   {
107c16b13ebSJoe Loser     DeletedConstConversionOperator dc;
108c16b13ebSJoe Loser     std::basic_string_view<char> sv = dc;
109c16b13ebSJoe Loser     assert(sv == "test");
110c16b13ebSJoe Loser   }
111c16b13ebSJoe Loser 
112c16b13ebSJoe Loser   return true;
113c16b13ebSJoe Loser }
114c16b13ebSJoe Loser 
115c16b13ebSJoe Loser static_assert(std::is_constructible_v<std::string_view, std::vector<char>&>);
116c16b13ebSJoe Loser static_assert(std::is_constructible_v<std::string_view, const std::vector<char>&>);
117c16b13ebSJoe Loser static_assert(std::is_constructible_v<std::string_view, std::vector<char>&&>);
118c16b13ebSJoe Loser static_assert(std::is_constructible_v<std::string_view, const std::vector<char>&&>);
119c16b13ebSJoe Loser 
120c16b13ebSJoe Loser using SizedButNotContiguousRange = std::ranges::subrange<random_access_iterator<char*>>;
121c16b13ebSJoe Loser static_assert(!std::ranges::contiguous_range<SizedButNotContiguousRange>);
122c16b13ebSJoe Loser static_assert(std::ranges::sized_range<SizedButNotContiguousRange>);
123c16b13ebSJoe Loser static_assert(!std::is_constructible_v<std::string_view, SizedButNotContiguousRange>);
124c16b13ebSJoe Loser 
125*2a04deccSArthur O'Dwyer using ContiguousButNotSizedRange = std::ranges::subrange<contiguous_iterator<char*>, sentinel_wrapper<contiguous_iterator<char*>>, std::ranges::subrange_kind::unsized>;
126c16b13ebSJoe Loser static_assert(std::ranges::contiguous_range<ContiguousButNotSizedRange>);
127c16b13ebSJoe Loser static_assert(!std::ranges::sized_range<ContiguousButNotSizedRange>);
128c16b13ebSJoe Loser static_assert(!std::is_constructible_v<std::string_view, ContiguousButNotSizedRange>);
129c16b13ebSJoe Loser 
130c16b13ebSJoe Loser static_assert(!std::is_constructible_v<std::string_view, std::vector<char16_t>>); // different CharT
131c16b13ebSJoe Loser 
132c16b13ebSJoe Loser struct WithStringViewConversionOperator {
133c16b13ebSJoe Loser   char* begin() const;
134c16b13ebSJoe Loser   char* end() const;
135c16b13ebSJoe Loser   operator std::string_view() const { return {}; }
136c16b13ebSJoe Loser };
137c16b13ebSJoe Loser 
138c16b13ebSJoe Loser static_assert(std::is_constructible_v<std::string_view, WithStringViewConversionOperator>); // lvalue
139c16b13ebSJoe Loser static_assert(std::is_constructible_v<std::string_view, const WithStringViewConversionOperator&>); // const lvalue
140c16b13ebSJoe Loser static_assert(std::is_constructible_v<std::string_view, WithStringViewConversionOperator&&>); // rvalue
141c16b13ebSJoe Loser 
142c16b13ebSJoe Loser template <class CharTraits>
143c16b13ebSJoe Loser struct WithTraitsType {
144c16b13ebSJoe Loser   typename CharTraits::char_type* begin() const;
145c16b13ebSJoe Loser   typename CharTraits::char_type* end() const;
146c16b13ebSJoe Loser   using traits_type = CharTraits;
147c16b13ebSJoe Loser };
148c16b13ebSJoe Loser 
149c16b13ebSJoe Loser using CCT = constexpr_char_traits<char>;
150c16b13ebSJoe Loser static_assert(std::is_constructible_v<std::string_view, WithTraitsType<std::char_traits<char>>>);
151c16b13ebSJoe Loser #ifndef TEST_HAS_NO_WIDE_CHARACTERS
152c16b13ebSJoe Loser static_assert(std::is_constructible_v<std::wstring_view, WithTraitsType<std::char_traits<wchar_t>>>);
153c16b13ebSJoe Loser #endif
154c16b13ebSJoe Loser static_assert(std::is_constructible_v<std::basic_string_view<char, CCT>, WithTraitsType<CCT>>);
155c16b13ebSJoe Loser static_assert(!std::is_constructible_v<std::string_view, WithTraitsType<CCT>>);  // wrong traits type
156c16b13ebSJoe Loser #ifndef TEST_HAS_NO_WIDE_CHARACTERS
157c16b13ebSJoe Loser static_assert(!std::is_constructible_v<std::wstring_view, WithTraitsType<std::char_traits<char>>>);  // wrong traits type
158c16b13ebSJoe Loser #endif
159c16b13ebSJoe Loser 
160c16b13ebSJoe Loser #ifndef TEST_HAS_NO_EXCEPTIONS
161c16b13ebSJoe Loser void test_throwing() {
162c16b13ebSJoe Loser   struct ThrowingData {
163c16b13ebSJoe Loser     char* begin() const { return nullptr; }
164c16b13ebSJoe Loser     char* end() const { return nullptr; }
165c16b13ebSJoe Loser     char* data() const { throw 42; return nullptr; }
166c16b13ebSJoe Loser   };
167c16b13ebSJoe Loser   try {
168c16b13ebSJoe Loser     ThrowingData x;
169c16b13ebSJoe Loser     (void) std::string_view(x);
170c16b13ebSJoe Loser     assert(false);
171c16b13ebSJoe Loser   } catch (int i) {
172c16b13ebSJoe Loser     assert(i == 42);
173c16b13ebSJoe Loser   }
174c16b13ebSJoe Loser 
175c16b13ebSJoe Loser   struct ThrowingSize {
176c16b13ebSJoe Loser     char* begin() const { return nullptr; }
177c16b13ebSJoe Loser     char* end() const { return nullptr; }
178c16b13ebSJoe Loser     size_t size() const { throw 42; return 0; }
179c16b13ebSJoe Loser   };
180c16b13ebSJoe Loser   try {
181c16b13ebSJoe Loser     ThrowingSize x;
182c16b13ebSJoe Loser     (void) std::string_view(x);
183c16b13ebSJoe Loser     assert(false);
184c16b13ebSJoe Loser   } catch (int i) {
185c16b13ebSJoe Loser     assert(i == 42);
186c16b13ebSJoe Loser   }
187c16b13ebSJoe Loser }
188c16b13ebSJoe Loser #endif
189c16b13ebSJoe Loser 
190c16b13ebSJoe Loser int main(int, char**) {
191c16b13ebSJoe Loser   test();
192c16b13ebSJoe Loser   static_assert(test());
193c16b13ebSJoe Loser #ifndef TEST_HAS_NO_EXCEPTIONS
194c16b13ebSJoe Loser   test_throwing();
195c16b13ebSJoe Loser #endif
196c16b13ebSJoe Loser 
197c16b13ebSJoe Loser   return 0;
198c16b13ebSJoe Loser }
199c16b13ebSJoe Loser 
200