xref: /llvm-project/libcxx/test/std/ranges/range.adaptors/range.elements/iterator/ctor.other.pass.cpp (revision d59a43fe2ad81f5c3918c9ef79a986955256f7ea)
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