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 // template<input_iterator I, class S>
12 // struct iterator_traits<common_iterator<I, S>>;
13
14 #include <iterator>
15
16 #include <cstddef>
17 #include "test_iterators.h"
18 #include "test_macros.h"
19 #include "types.h"
20
21 template<class T>
22 concept HasIteratorConcept = requires { typename T::iterator_concept; };
23
24 struct NonVoidOutputIterator {
25 using value_type = int;
26 using difference_type = std::ptrdiff_t;
27 const NonVoidOutputIterator& operator*() const;
28 NonVoidOutputIterator& operator++();
29 NonVoidOutputIterator& operator++(int);
30 void operator=(int) const;
31 };
32
test()33 void test() {
34 {
35 using Iter = simple_iterator<int*>;
36 using CommonIter = std::common_iterator<Iter, sentinel_type<int*>>;
37 using IterTraits = std::iterator_traits<CommonIter>;
38
39 static_assert(std::same_as<IterTraits::iterator_concept, std::input_iterator_tag>);
40 static_assert(std::same_as<IterTraits::iterator_category, std::input_iterator_tag>);
41 static_assert(std::same_as<IterTraits::value_type, int>);
42 static_assert(std::same_as<IterTraits::difference_type, std::ptrdiff_t>);
43 static_assert(std::same_as<IterTraits::pointer, int*>);
44 static_assert(std::same_as<IterTraits::reference, int&>);
45 }
46 {
47 using Iter = value_iterator<int*>;
48 using CommonIter = std::common_iterator<Iter, sentinel_type<int*>>;
49 using IterTraits = std::iterator_traits<CommonIter>;
50
51 static_assert(std::same_as<IterTraits::iterator_concept, std::input_iterator_tag>);
52 static_assert(std::same_as<IterTraits::iterator_category, std::input_iterator_tag>);
53 static_assert(std::same_as<IterTraits::value_type, int>);
54 static_assert(std::same_as<IterTraits::difference_type, std::ptrdiff_t>);
55 // Note: IterTraits::pointer == __proxy.
56 static_assert(!std::same_as<IterTraits::pointer, int*>);
57 static_assert(std::same_as<IterTraits::reference, int>);
58 }
59 // Test with an output_iterator that has a void value_type
60 {
61 using Iter = cpp17_output_iterator<int*>;
62 using CommonIter = std::common_iterator<Iter, sentinel_type<int*>>;
63 using IterTraits = std::iterator_traits<CommonIter>;
64
65 static_assert(!HasIteratorConcept<IterTraits>);
66 static_assert(std::same_as<IterTraits::iterator_category, std::output_iterator_tag>);
67 static_assert(std::same_as<IterTraits::value_type, void>);
68 static_assert(std::same_as<IterTraits::difference_type, std::ptrdiff_t>);
69 static_assert(std::same_as<IterTraits::pointer, void>);
70 static_assert(std::same_as<IterTraits::reference, void>);
71 }
72 // Test with an output_iterator that has a non-void value_type
73 {
74 using CommonIter = std::common_iterator<NonVoidOutputIterator, sentinel_wrapper<NonVoidOutputIterator>>;
75 using IterTraits = std::iterator_traits<CommonIter>;
76
77 static_assert(!HasIteratorConcept<IterTraits>);
78 static_assert(std::same_as<IterTraits::iterator_category, std::output_iterator_tag>);
79 static_assert(std::same_as<IterTraits::value_type, void>);
80 static_assert(std::same_as<IterTraits::difference_type, std::ptrdiff_t>);
81 static_assert(std::same_as<IterTraits::pointer, void>);
82 static_assert(std::same_as<IterTraits::reference, void>);
83 }
84 {
85 using Iter = cpp17_input_iterator<int*>;
86 using CommonIter = std::common_iterator<Iter, sentinel_type<int*>>;
87 using IterTraits = std::iterator_traits<CommonIter>;
88
89 static_assert(std::same_as<IterTraits::iterator_concept, std::input_iterator_tag>);
90 static_assert(std::same_as<IterTraits::iterator_category, std::input_iterator_tag>);
91 static_assert(std::same_as<IterTraits::value_type, int>);
92 static_assert(std::same_as<IterTraits::difference_type, std::ptrdiff_t>);
93 static_assert(std::same_as<IterTraits::pointer, int*>);
94 static_assert(std::same_as<IterTraits::reference, int&>);
95 }
96 {
97 using Iter = forward_iterator<int*>;
98 using CommonIter = std::common_iterator<Iter, sentinel_type<int*>>;
99 using IterTraits = std::iterator_traits<CommonIter>;
100
101 static_assert(std::same_as<IterTraits::iterator_concept, std::forward_iterator_tag>);
102 static_assert(std::same_as<IterTraits::iterator_category, std::forward_iterator_tag>);
103 static_assert(std::same_as<IterTraits::value_type, int>);
104 static_assert(std::same_as<IterTraits::difference_type, std::ptrdiff_t>);
105 static_assert(std::same_as<IterTraits::pointer, int*>);
106 static_assert(std::same_as<IterTraits::reference, int&>);
107 }
108 {
109 using Iter = random_access_iterator<int*>;
110 using CommonIter = std::common_iterator<Iter, sentinel_type<int*>>;
111 using IterTraits = std::iterator_traits<CommonIter>;
112
113 static_assert(std::same_as<IterTraits::iterator_concept, std::forward_iterator_tag>);
114 static_assert(std::same_as<IterTraits::iterator_category, std::forward_iterator_tag>);
115 static_assert(std::same_as<IterTraits::value_type, int>);
116 static_assert(std::same_as<IterTraits::difference_type, std::ptrdiff_t>);
117 static_assert(std::same_as<IterTraits::pointer, int*>);
118 static_assert(std::same_as<IterTraits::reference, int&>);
119 }
120
121 // Testing iterator conformance.
122 {
123 static_assert(std::input_iterator<std::common_iterator<cpp17_input_iterator<int*>, sentinel_type<int*>>>);
124 static_assert(std::forward_iterator<std::common_iterator<forward_iterator<int*>, sentinel_type<int*>>>);
125 static_assert(std::forward_iterator<std::common_iterator<random_access_iterator<int*>, sentinel_type<int*>>>);
126 static_assert(std::forward_iterator<std::common_iterator<contiguous_iterator<int*>, sentinel_type<int*>>>);
127 // Even these are only forward.
128 static_assert(!std::bidirectional_iterator<std::common_iterator<random_access_iterator<int*>, sentinel_type<int*>>>);
129 static_assert(!std::bidirectional_iterator<std::common_iterator<contiguous_iterator<int*>, sentinel_type<int*>>>);
130
131 using Iter = std::common_iterator<forward_iterator<int*>, sentinel_type<int*>>;
132 static_assert(std::indirectly_writable<Iter, int>);
133 static_assert(std::indirectly_swappable<Iter, Iter>);
134 }
135 }
136