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