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

source code of libcxx/test/std/strings/string.view/string.view.cons/from_range.pass.cpp