198 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8// UNSUPPORTED: c++03, c++11, c++14, c++17, c++209 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_CHARACTERS44 test<wchar_t>();45#endif46 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-const63 }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 types110 {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 CharT140 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>); // lvalue148static_assert(std::is_constructible_v<std::string_view, const WithStringViewConversionOperator&>); // const lvalue149static_assert(std::is_constructible_v<std::string_view, WithStringViewConversionOperator&&>); // rvalue150 151#ifndef TEST_HAS_NO_EXCEPTIONS152void 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#endif186 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_EXCEPTIONS193 test_throwing();194#endif195 196 return 0;197}198