//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 // UNSUPPORTED: libcpp-has-no-incomplete-ranges // // template // constexpr basic_string_view(Range&& range); #include #include #include #include #include #include #include #include "constexpr_char_traits.h" #include "make_string.h" #include "test_iterators.h" #include "test_range.h" template constexpr void test() { auto data = MAKE_STRING_VIEW(CharT, "test"); std::array arr; for(int i = 0; i < 4; ++i) { arr[i] = data[i]; } auto sv = std::basic_string_view(arr); ASSERT_SAME_TYPE(decltype(sv), std::basic_string_view); assert(sv.size() == arr.size()); assert(sv.data() == arr.data()); } constexpr bool test() { test(); #ifndef TEST_HAS_NO_WIDE_CHARACTERS test(); #endif test(); test(); test(); { struct NonConstConversionOperator { const char* data_ = "test"; constexpr const char* begin() const { return data_; } constexpr const char* end() const { return data_ + 4; } constexpr operator std::basic_string_view() { return "NonConstConversionOp"; } }; NonConstConversionOperator nc; std::string_view sv = nc; assert(sv == "NonConstConversionOp"); static_assert(!std::is_constructible_v); // conversion operator is non-const } { struct ConstConversionOperator { const char* data_ = "test"; constexpr const char* begin() const { return data_; } constexpr const char* end() const { return data_ + 4; } constexpr operator std::basic_string_view() const { return "ConstConversionOp"; } }; ConstConversionOperator cv; std::basic_string_view sv = cv; assert(sv == "ConstConversionOp"); } struct DeletedConversionOperator { const char* data_ = "test"; constexpr const char* begin() const { return data_; } constexpr const char* end() const { return data_ + 4; } operator std::basic_string_view() = delete; }; struct DeletedConstConversionOperator { const char* data_ = "test"; constexpr const char* begin() const { return data_; } constexpr const char* end() const { return data_ + 4; } operator std::basic_string_view() const = delete; }; static_assert(std::is_constructible_v); static_assert(std::is_constructible_v); static_assert(std::is_constructible_v); static_assert(std::is_constructible_v); // Test that we're not trying to use the type's conversion operator to string_view in the constructor. { const DeletedConversionOperator d; std::basic_string_view csv = d; assert(csv == "test"); } { DeletedConstConversionOperator dc; std::basic_string_view sv = dc; assert(sv == "test"); } return true; } static_assert(std::is_constructible_v&>); static_assert(std::is_constructible_v&>); static_assert(std::is_constructible_v&&>); static_assert(std::is_constructible_v&&>); using SizedButNotContiguousRange = std::ranges::subrange>; static_assert(!std::ranges::contiguous_range); static_assert(std::ranges::sized_range); static_assert(!std::is_constructible_v); using ContiguousButNotSizedRange = std::ranges::subrange, sentinel_wrapper>, std::ranges::subrange_kind::unsized>; static_assert(std::ranges::contiguous_range); static_assert(!std::ranges::sized_range); static_assert(!std::is_constructible_v); static_assert(!std::is_constructible_v>); // different CharT struct WithStringViewConversionOperator { char* begin() const; char* end() const; operator std::string_view() const { return {}; } }; static_assert(std::is_constructible_v); // lvalue static_assert(std::is_constructible_v); // const lvalue static_assert(std::is_constructible_v); // rvalue template struct WithTraitsType { typename CharTraits::char_type* begin() const; typename CharTraits::char_type* end() const; using traits_type = CharTraits; }; using CCT = constexpr_char_traits; static_assert(std::is_constructible_v>>); #ifndef TEST_HAS_NO_WIDE_CHARACTERS static_assert(std::is_constructible_v>>); #endif static_assert(std::is_constructible_v, WithTraitsType>); static_assert(!std::is_constructible_v>); // wrong traits type #ifndef TEST_HAS_NO_WIDE_CHARACTERS static_assert(!std::is_constructible_v>>); // wrong traits type #endif #ifndef TEST_HAS_NO_EXCEPTIONS void test_throwing() { struct ThrowingData { char* begin() const { return nullptr; } char* end() const { return nullptr; } char* data() const { throw 42; return nullptr; } }; try { ThrowingData x; (void) std::string_view(x); assert(false); } catch (int i) { assert(i == 42); } struct ThrowingSize { char* begin() const { return nullptr; } char* end() const { return nullptr; } size_t size() const { throw 42; return 0; } }; try { ThrowingSize x; (void) std::string_view(x); assert(false); } catch (int i) { assert(i == 42); } } #endif int main(int, char**) { test(); static_assert(test()); #ifndef TEST_HAS_NO_EXCEPTIONS test_throwing(); #endif return 0; }