@@ -35,18 +35,36 @@ namespace llvm {
3535template <typename DerivedT, typename IteratorCategoryT, typename T,
3636 typename DifferenceTypeT = std::ptrdiff_t , typename PointerT = T *,
3737 typename ReferenceT = T &>
38- struct iterator_facade_base
39- : std::iterator<IteratorCategoryT, T, DifferenceTypeT, PointerT,
40- ReferenceT> {
38+ class iterator_facade_base
39+ : public std::iterator<IteratorCategoryT, T, DifferenceTypeT, PointerT,
40+ ReferenceT> {
41+ protected:
42+ enum {
43+ IsRandomAccess =
44+ std::is_base_of<std::random_access_iterator_tag, IteratorCategoryT>::value,
45+ IsBidirectional =
46+ std::is_base_of<std::bidirectional_iterator_tag, IteratorCategoryT>::value,
47+ };
48+
49+ public:
4150 DerivedT operator +(DifferenceTypeT n) const {
51+ static_assert (
52+ IsRandomAccess,
53+ " The '+' operator is only defined for random access iterators." );
4254 DerivedT tmp = *static_cast <const DerivedT *>(this );
4355 tmp += n;
4456 return tmp;
4557 }
4658 friend DerivedT operator +(DifferenceTypeT n, const DerivedT &i) {
59+ static_assert (
60+ IsRandomAccess,
61+ " The '+' operator is only defined for random access iterators." );
4762 return i + n;
4863 }
4964 DerivedT operator -(DifferenceTypeT n) const {
65+ static_assert (
66+ IsRandomAccess,
67+ " The '-' operator is only defined for random access iterators." );
5068 DerivedT tmp = *static_cast <const DerivedT *>(this );
5169 tmp -= n;
5270 return tmp;
@@ -61,9 +79,15 @@ struct iterator_facade_base
6179 return tmp;
6280 }
6381 DerivedT &operator --() {
82+ static_assert (
83+ IsBidirectional,
84+ " The decrement operator is only defined for bidirectional iterators." );
6485 return static_cast <DerivedT *>(this )->operator -=(1 );
6586 }
6687 DerivedT operator --(int ) {
88+ static_assert (
89+ IsBidirectional,
90+ " The decrement operator is only defined for bidirectional iterators." );
6791 DerivedT tmp = *static_cast <DerivedT *>(this );
6892 --*static_cast <DerivedT *>(this );
6993 return tmp;
@@ -74,20 +98,31 @@ struct iterator_facade_base
7498 }
7599
76100 bool operator >(const DerivedT &RHS) const {
101+ static_assert (
102+ IsRandomAccess,
103+ " Relational operators are only defined for random access iterators." );
77104 return !static_cast <const DerivedT *>(this )->operator <(RHS) &&
78105 !static_cast <const DerivedT *>(this )->operator ==(RHS);
79106 }
80107 bool operator <=(const DerivedT &RHS) const {
108+ static_assert (
109+ IsRandomAccess,
110+ " Relational operators are only defined for random access iterators." );
81111 return !static_cast <const DerivedT *>(this )->operator >(RHS);
82112 }
83113 bool operator >=(const DerivedT &RHS) const {
114+ static_assert (
115+ IsRandomAccess,
116+ " Relational operators are only defined for random access iterators." );
84117 return !static_cast <const DerivedT *>(this )->operator <(RHS);
85118 }
86119
87120 PointerT operator ->() const {
88121 return &static_cast <const DerivedT *>(this )->operator *();
89122 }
90123 ReferenceT operator [](DifferenceTypeT n) const {
124+ static_assert (IsRandomAccess,
125+ " Subscripting is only defined for random access iterators." );
91126 return *static_cast <const DerivedT *>(this )->operator +(n);
92127 }
93128};
@@ -131,15 +166,26 @@ class iterator_adaptor_base
131166 typedef DifferenceTypeT difference_type;
132167
133168 DerivedT &operator +=(difference_type n) {
169+ static_assert (
170+ BaseT::IsRandomAccess,
171+ " The '+=' operator is only defined for random access iterators." );
134172 I += n;
135173 return *static_cast <DerivedT *>(this );
136174 }
137175 DerivedT &operator -=(difference_type n) {
176+ static_assert (
177+ BaseT::IsRandomAccess,
178+ " The '-=' operator is only defined for random access iterators." );
138179 I -= n;
139180 return *static_cast <DerivedT *>(this );
140181 }
141182 using BaseT::operator -;
142- difference_type operator -(const DerivedT &RHS) const { return I - RHS.I ; }
183+ difference_type operator -(const DerivedT &RHS) const {
184+ static_assert (
185+ BaseT::IsRandomAccess,
186+ " The '-' operator is only defined for random access iterators." );
187+ return I - RHS.I ;
188+ }
143189
144190 // We have to explicitly provide ++ and -- rather than letting the facade
145191 // forward to += because WrappedIteratorT might not support +=.
@@ -150,12 +196,20 @@ class iterator_adaptor_base
150196 }
151197 using BaseT::operator --;
152198 DerivedT &operator --() {
199+ static_assert (
200+ BaseT::IsBidirectional,
201+ " The decrement operator is only defined for bidirectional iterators." );
153202 --I;
154203 return *static_cast <DerivedT *>(this );
155204 }
156205
157206 bool operator ==(const DerivedT &RHS) const { return I == RHS.I ; }
158- bool operator <(const DerivedT &RHS) const { return I < RHS.I ; }
207+ bool operator <(const DerivedT &RHS) const {
208+ static_assert (
209+ BaseT::IsRandomAccess,
210+ " Relational operators are only defined for random access iterators." );
211+ return I < RHS.I ;
212+ }
159213
160214 ReferenceT operator *() const { return *I; }
161215};
0 commit comments