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 iterator(iterator<!Const> i)
12 // requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>;
13
14 #include <cassert>
15 #include <ranges>
16 #include <tuple>
17
18 #include "../types.h"
19
20 template <bool Const>
21 struct ConvertibleIter : IterBase<ConvertibleIter<Const>> {
22 using iterator_category = std::random_access_iterator_tag;
23 using value_type = std::tuple<int>;
24 using difference_type = std::intptr_t;
25
26 bool movedFromOtherConst = false;
27 int i = 0;
28
29 constexpr ConvertibleIter() = default;
ConvertibleIterConvertibleIter30 constexpr ConvertibleIter(int ii) : i(ii) {}
31 template <bool otherConst>
32 requires(Const != otherConst)
ConvertibleIterConvertibleIter33 constexpr ConvertibleIter(ConvertibleIter<otherConst> it) : movedFromOtherConst(true), i(it.i) {}
34 };
35
36 template <class Iter, class ConstIter>
37 struct BasicView : std::ranges::view_base {
38 Iter begin();
39 Iter end();
40
41 ConstIter begin() const;
42 ConstIter end() const;
43 };
44
45 template <class View>
46 using ElemIter = std::ranges::iterator_t<std::ranges::elements_view<View, 0>>;
47
48 template <class View>
49 using ConstElemIter = std::ranges::iterator_t<const std::ranges::elements_view<View, 0>>;
50
51 using ConvertibleView = BasicView<ConvertibleIter<false>, ConvertibleIter<true>>;
52 using NonConvertibleView = BasicView<forward_iterator<std::tuple<int>*>, bidirectional_iterator<std::tuple<int>*>>;
53
54 static_assert(std::is_constructible_v<ConstElemIter<ConvertibleView>, ElemIter<ConvertibleView>>);
55 static_assert(!std::is_constructible_v<ElemIter<ConvertibleView>, ConstElemIter<ConvertibleView>>);
56 static_assert(!std::is_constructible_v<ConstElemIter<NonConvertibleView>, ElemIter<NonConvertibleView>>);
57 static_assert(!std::is_constructible_v<ElemIter<NonConvertibleView>, ConstElemIter<NonConvertibleView>>);
58
test()59 constexpr bool test() {
60 ElemIter<ConvertibleView> iter{ConvertibleIter<false>{5}};
61 ConstElemIter<ConvertibleView> constIter = iter; // implicit
62 assert(constIter.base().movedFromOtherConst);
63 assert(constIter.base().i == 5);
64
65 return true;
66 }
67
main(int,char **)68 int main(int, char**) {
69 test();
70 static_assert(test());
71
72 return 0;
73 }
74