//===----------------------------------------------------------------------===// // // 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 // // template // constexpr basic_string_view(Range&& range); #include #include #include #include #include #include #include #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 = std::basic_string_view(d); assert(csv == "test"); } { DeletedConstConversionOperator dc; std::basic_string_view sv = std::basic_string_view(dc); assert(sv == "test"); } // Different trait types { struct OtherTraits : std::char_traits {}; std::basic_string_view sv1{"hello"}; std::basic_string_view sv2(sv1); assert(sv1.size() == sv2.size()); assert(sv1.data() == sv2.data()); } 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 #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; } std::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 static_assert(!std::is_convertible_v, std::string_view>); int main(int, char**) { test(); static_assert(test()); #ifndef TEST_HAS_NO_EXCEPTIONS test_throwing(); #endif return 0; }