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