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 // <iterator>
10 
11 // move_iterator
12 
13 // template <class U>
14 //   requires HasAssign<Iter, const U&>
15 //   move_iterator&
16 //   operator=(const move_iterator<U>& u);
17 //
18 //  constexpr in C++17
19 
20 #include <iterator>
21 #include <cassert>
22 
23 #include "test_macros.h"
24 #include "test_iterators.h"
25 
26 template <class It, class U>
27 void
test(U u)28 test(U u)
29 {
30     const std::move_iterator<U> r2(u);
31     std::move_iterator<It> r1(It(nullptr));
32     std::move_iterator<It>& rr = (r1 = r2);
33     assert(base(r1.base()) == base(u));
34     assert(&rr == &r1);
35 }
36 
37 struct Base {};
38 struct Derived : Base {};
39 
40 struct ToIter {
41     typedef std::forward_iterator_tag iterator_category;
42     typedef char *pointer;
43     typedef char &reference;
44     typedef char value_type;
45     typedef signed char difference_type;
46 
ToIterToIter47     explicit TEST_CONSTEXPR_CXX17 ToIter() : m_value(0) {}
ToIterToIter48     TEST_CONSTEXPR_CXX17 ToIter(const ToIter &src) : m_value(src.m_value) {}
49     // Intentionally not defined, must not be called.
50     ToIter(char *src);
operator =ToIter51     TEST_CONSTEXPR_CXX17 ToIter &operator=(char *src) {
52         m_value = src;
53         return *this;
54     }
operator =ToIter55     TEST_CONSTEXPR_CXX17 ToIter &operator=(const ToIter &src) {
56         m_value = src.m_value;
57         return *this;
58     }
59     char *m_value;
60 
61     reference operator*() const;
62 };
63 
test_conv_assign()64 TEST_CONSTEXPR_CXX17 bool test_conv_assign()
65 {
66     char c = '\0';
67     char *fi = &c;
68     const std::move_iterator<char *> move_fi(fi);
69     std::move_iterator<ToIter> move_ti;
70     move_ti = move_fi;
71     assert(move_ti.base().m_value == fi);
72     return true;
73 }
74 
main(int,char **)75 int main(int, char**)
76 {
77     Derived d;
78 
79     test<cpp17_input_iterator<Base*> >(cpp17_input_iterator<Derived*>(&d));
80     test<forward_iterator<Base*> >(forward_iterator<Derived*>(&d));
81     test<bidirectional_iterator<Base*> >(bidirectional_iterator<Derived*>(&d));
82     test<random_access_iterator<const Base*> >(random_access_iterator<Derived*>(&d));
83     test<Base*>(&d);
84     test_conv_assign();
85 #if TEST_STD_VER > 14
86     {
87     using BaseIter    = std::move_iterator<const Base *>;
88     using DerivedIter = std::move_iterator<const Derived *>;
89     constexpr const Derived *p = nullptr;
90     constexpr DerivedIter     it1 = std::make_move_iterator(p);
91     constexpr BaseIter        it2 = (BaseIter{nullptr} = it1);
92     static_assert(it2.base() == p, "");
93     static_assert(test_conv_assign(), "");
94     }
95 #endif
96 
97   return 0;
98 }
99