xref: /llvm-project/libcxx/test/std/ranges/range.adaptors/range.join/range.join.sentinel/ctor.other.pass.cpp (revision 98e3d98bf34ff9202e8b82d4967c02e4fd7d6532)
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 
11 // constexpr sentinel(sentinel<!Const> s);
12 //             requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
13 
14 #include <cassert>
15 #include <ranges>
16 
17 #include "../types.h"
18 #include "test_range.h"
19 
20 template <class T>
21 struct convertible_sentinel_wrapper {
22   explicit convertible_sentinel_wrapper() = default;
convertible_sentinel_wrapperconvertible_sentinel_wrapper23   constexpr convertible_sentinel_wrapper(const T& it) : it_(it) {}
24 
25   template <class U>
26     requires std::convertible_to<const U&, T>
convertible_sentinel_wrapperconvertible_sentinel_wrapper27   constexpr convertible_sentinel_wrapper(const convertible_sentinel_wrapper<U>& other) : it_(other.it_) {}
28 
operator ==(convertible_sentinel_wrapper const & self,const T & other)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 ConstConvertibleView : 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 
beginConstConvertibleView41   constexpr BufferView<int*>* begin() { return data_; }
beginConstConvertibleView42   constexpr const BufferView<int*>* begin() const { return data_; }
endConstConvertibleView43   constexpr sentinel end() { return sentinel(data_ + size_); }
endConstConvertibleView44   constexpr const_sentinel end() const { return const_sentinel(data_ + size_); }
45 };
46 static_assert(!std::ranges::common_range<ConstConvertibleView>);
47 static_assert(std::convertible_to<std::ranges::sentinel_t<ConstConvertibleView>,
48                                   std::ranges::sentinel_t<ConstConvertibleView const>>);
49 static_assert(!simple_view<ConstConvertibleView>);
50 
test()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     ConstConvertibleView 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_t     = std::ranges::sentinel_t<JoinView>;
75     using const_sentinel_t = std::ranges::sentinel_t<const JoinView>;
76     static_assert(!std::constructible_from<sentinel_t, const_sentinel_t>);
77     static_assert(!std::constructible_from<const_sentinel_t, sentinel_t>);
78   }
79   return true;
80 }
81 
main(int,char **)82 int main(int, char**) {
83   test();
84   static_assert(test());
85 
86   return 0;
87 }
88