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 9 // UNSUPPORTED: c++03, c++11, c++14, c++17 10 // UNSUPPORTED: libcpp-has-no-incomplete-ranges 11 12 // constexpr sentinel(sentinel<!Const> s); 13 // requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>; 14 15 #include <cassert> 16 #include <ranges> 17 18 #include "../types.h" 19 20 template <class T> 21 struct convertible_sentinel_wrapper { 22 explicit convertible_sentinel_wrapper() = default; 23 constexpr convertible_sentinel_wrapper(const T& it) : it_(it) {} 24 25 template <class U> 26 requires std::convertible_to<const U&, T> 27 constexpr convertible_sentinel_wrapper(const convertible_sentinel_wrapper<U>& other) : it_(other.it_) {} 28 29 constexpr friend bool operator==(convertible_sentinel_wrapper const& self, const T& other) { 30 return self.it_ == other; 31 } 32 T it_; 33 }; 34 35 struct ConstConveritbleView : BufferView<BufferView<int*>*> { 36 using BufferView<BufferView<int*>*>::BufferView; 37 38 using sentinel = convertible_sentinel_wrapper<BufferView<int*>*>; 39 using const_sentinel = convertible_sentinel_wrapper<const BufferView<int*>*>; 40 41 constexpr BufferView<int*>* begin() { return data_; } 42 constexpr const BufferView<int*>* begin() const { return data_; } 43 constexpr sentinel end() { return sentinel(data_ + size_); } 44 constexpr const_sentinel end() const { return const_sentinel(data_ + size_); } 45 }; 46 static_assert(!std::ranges::common_range<ConstConveritbleView>); 47 static_assert(std::convertible_to<std::ranges::sentinel_t<ConstConveritbleView>, 48 std::ranges::sentinel_t<ConstConveritbleView const>>); 49 LIBCPP_STATIC_ASSERT(!std::ranges::__simple_view<ConstConveritbleView>); 50 51 constexpr bool test() { 52 int buffer[4][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}, {13, 14, 15, 16}}; 53 { 54 BufferView<int*> inners[] = {buffer[0], buffer[1], buffer[2]}; 55 ConstConveritbleView outer(inners); 56 std::ranges::join_view jv(outer); 57 auto sent1 = jv.end(); 58 std::ranges::sentinel_t<const decltype(jv)> sent2 = sent1; 59 assert(std::as_const(jv).begin() != sent2); 60 assert(std::ranges::next(std::as_const(jv).begin(), 12) == sent2); 61 62 // We cannot create a non-const sentinel from a const sentinel. 63 static_assert(!std::constructible_from<decltype(sent1), decltype(sent2)>); 64 } 65 66 { 67 // cannot create a const sentinel from a non-const sentinel if the underlying 68 // const sentinel cannot be created from the underlying non-const sentinel 69 using Inner = BufferView<int*>; 70 using ConstInconvertibleOuter = 71 BufferView<forward_iterator<const Inner*>, sentinel_wrapper<forward_iterator<const Inner*>>, 72 bidirectional_iterator<Inner*>, sentinel_wrapper<bidirectional_iterator<Inner*>>>; 73 using JoinView = std::ranges::join_view<ConstInconvertibleOuter>; 74 using sentinel = std::ranges::sentinel_t<JoinView>; 75 using const_sentinel = std::ranges::sentinel_t<const JoinView>; 76 static_assert(!std::constructible_from<sentinel, const_sentinel>); 77 static_assert(!std::constructible_from<const_sentinel, sentinel>); 78 } 79 return true; 80 } 81 82 int main(int, char**) { 83 test(); 84 static_assert(test()); 85 86 return 0; 87 } 88