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