1// 24.1.5 Random access iterators
2// 24.3.1 Iterator traits
3// (basic_string and vector implementations)
4//
5// Copyright (C) 1999-2015 Free Software Foundation, Inc.
6// This program is free software; you can redistribute it and/or modify
7// it under the terms of the GNU General Public License as published by
8// the Free Software Foundation; either version 3 of the License, or
9// (at your option) any later version.
10//
11// This program is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14// GNU General Public License for more details.
15//
16// You should have received a copy of the GNU General Public License
17// along with this program; see the file COPYING3.  If not see
18// <http://www.gnu.org/licenses/>.
19
20
21#include <string>
22#include <vector>
23#include <testsuite_hooks.h>
24
25int
26string_stuff()
27{
28   int failures(0);
29
30   std::string s("abcde");
31
32   std::string::iterator i1(s.begin());
33   if (*i1 != 'a')
34      ++failures;
35
36   ++i1;
37   if (*i1 != 'b')
38      ++failures;
39
40   if (*i1++ != 'b')
41       ++failures;
42   if (*i1 != 'c')
43      ++failures;
44
45   ++ ++i1;
46   if (*i1 != 'e')
47      ++failures;
48
49   --i1;
50   if (*i1 != 'd')
51      ++failures;
52
53   if (*i1-- != 'd')
54      ++failures;
55   if (*i1 != 'c')
56      ++failures;
57
58   -- --i1;
59   if (*i1 != 'a')
60      ++failures;
61
62   std::string::iterator i2;
63   i2 = s.end();
64   std::iterator_traits<std::string::iterator>::difference_type d1;
65   d1 = i2 - i1;
66   if (d1 != 5)
67      ++failures;
68
69   std::iterator_traits<std::string::iterator>::value_type v1;
70   v1 = i1[0];
71   if (v1 != 'a')
72      ++failures;
73
74   std::iterator_traits<std::string::iterator>::reference r1(i1[0]);
75   if (r1 != 'a')
76      ++failures;
77   r1 = 'x';
78   if (r1 != 'x')
79      ++failures;
80   r1 = 'a';
81
82   if ((i1 != i2) != true)
83      ++failures;
84   if ((i1 == i2) != false)
85      ++failures;
86   if ((i1 <  i2) != true)
87      ++failures;
88   if ((i1 >  i2) != false)
89      ++failures;
90   if ((i1 <= i2) != true)
91      ++failures;
92   if ((i1 >= i2) != false)
93      ++failures;
94
95   std::string::iterator i3;
96   i3 = i1;
97   if ((i3 == i1) != true)
98      ++failures;
99
100   i3 += 5;
101   if ((i3 == i2) != true)
102      ++failures;
103
104   i3 -= 5;
105   if ((i3 == i1) != true)
106      ++failures;
107
108   if (i3 + 5 != i2)
109      ++failures;
110
111   if (5 + i3 != i2)
112      ++failures;
113
114   if (i2 - 5 != i3)
115      ++failures;
116
117   if (i1[0] != 'a')
118      ++failures;
119
120   i1[4] = 'x';
121   if (i2[-1] != 'x')
122      ++failures;
123   i1[4] = 'e';
124
125   i1[2] = 'x';
126   if (i2[-3] != 'x')
127      ++failures;
128   i1[2] = 'c';
129
130   std::string::const_iterator ci1(s.begin());
131   if (*ci1 != 'a')
132      ++failures;
133
134   ++ci1;
135   if (*ci1 != 'b')
136      ++failures;
137
138   if (*ci1++ != 'b')
139      ++failures;
140   if (*ci1 != 'c')
141      ++failures;
142
143   ++ ++ci1;
144   if (*ci1 != 'e')
145      ++failures;
146
147   --ci1;
148   if (*ci1 != 'd')
149      ++failures;
150
151   if (*ci1-- != 'd')
152      ++failures;
153   if (*ci1 != 'c')
154      ++failures;
155
156   -- --ci1;
157   if (*ci1 != 'a')
158      ++failures;
159
160   std::string::const_iterator ci2;
161   ci2 = s.end();
162   std::iterator_traits<std::string::const_iterator>::difference_type d2;
163   d2 = ci2 - ci1;
164   if (d2 != 5)
165     ++failures;
166
167   std::iterator_traits<std::string::const_iterator>::value_type v2;
168   v2 = ci1[0];
169   if (v2 != 'a')
170     ++failures;
171
172   std::iterator_traits<std::string::const_iterator>::reference r2(ci1[0]);
173   if (r2 != 'a')
174      ++failures;
175
176   if ((ci1 != ci2) != true)
177      ++failures;
178   if ((ci1 == ci2) != false)
179      ++failures;
180   if ((ci1 <  ci2) != true)
181      ++failures;
182   if ((ci1 >  ci2) != false)
183      ++failures;
184   if ((ci1 <= ci2) != true)
185      ++failures;
186   if ((ci1 >= ci2) != false)
187      ++failures;
188
189   std::string::const_iterator ci3;
190   ci3 = ci1;
191   if ((ci3 == ci1) != true)
192      ++failures;
193
194   ci3 += 5;
195   if ((ci3 == ci2) != true)
196      ++failures;
197
198   ci3 -= 5;
199   if ((ci3 == ci1) != true)
200      ++failures;
201
202   if (ci3 + 5 != ci2)
203      ++failures;
204
205   if (5 + ci3 != ci2)
206      ++failures;
207
208   if (ci2 - 5 != ci3)
209      ++failures;
210
211   if (ci1[2] != 'c')
212      ++failures;
213
214   if (ci2[-1] != 'e')
215      ++failures;
216
217   // iterator and const_iterator
218   std::string::const_iterator ci4(i1);
219   if ((ci4 == i1) != true)
220      ++failures;
221   if ((ci4 != i1) != false)
222      ++failures;
223   if ((ci4 < i1)  != false)
224     ++failures;
225   if ((ci4 > i1)  != false)
226     ++failures;
227   if ((ci4 <= i1) != true)
228     ++failures;
229   if ((ci4 >= i1) != true)
230     ++failures;
231   ci4 = i2;
232   if ((i2 == ci4) != true)
233     ++failures;
234   if ((i2 < ci4)  != false)
235     ++failures;
236   if ((i2 > ci4)  != false)
237     ++failures;
238   if ((i2 <= ci4) != true)
239     ++failures;
240   if ((i2 >= ci4) != true)
241     ++failures;
242
243   const std::string cs("ABCDE");
244   std::string::const_iterator ci5(cs.begin());
245   if (ci5[0] != 'A')
246      ++failures;
247
248   return failures;
249}
250
251int
252vector_stuff()
253{
254   int failures(0);
255
256   std::vector<int> v;
257   v.push_back(int(1));
258   v.push_back(int(2));
259   v.push_back(int(3));
260   v.push_back(int(4));
261   v.push_back(int(5));
262
263   std::vector<int>::iterator i1(v.begin());
264   if (*i1 != 1)
265      ++failures;
266
267   ++i1;
268   if (*i1 != 2)
269      ++failures;
270
271   if (*i1++ != 2)
272      ++failures;
273   if (*i1 != 3)
274      ++failures;
275
276   ++ ++i1;
277   if (*i1 != 5)
278      ++failures;
279
280   --i1;
281   if (*i1 != 4)
282      ++failures;
283
284   if (*i1-- != 4)
285      ++failures;
286   if (*i1 != 3)
287      ++failures;
288
289   -- --i1;
290   if (*i1 != 1)
291      ++failures;
292
293   std::vector<int>::iterator i2;
294   i2 = v.end();
295   std::iterator_traits<std::vector<int>::iterator>::difference_type d1;
296   d1 = i2 - i1;
297   if (d1 != 5)
298      ++failures;
299
300   std::iterator_traits<std::vector<int>::iterator>::value_type v1;
301   v1 = i1[0];
302   if (v1 != 1)
303      ++failures;
304
305   std::iterator_traits<std::vector<int>::iterator>::reference r1(i1[0]);
306   if (r1 != 1)
307      ++failures;
308   r1 = 9;
309   if (r1 != 9)
310      ++failures;
311   r1 = 1;
312
313   if ((i1 != i2) != true)
314      ++failures;
315   if ((i1 == i2) != false)
316      ++failures;
317   if ((i1 <  i2) != true)
318      ++failures;
319   if ((i1 >  i2) != false)
320      ++failures;
321   if ((i1 <= i2) != true)
322      ++failures;
323   if ((i1 >= i2) != false)
324      ++failures;
325
326   std::vector<int>::iterator i3;
327   i3 = i1;
328   if ((i3 == i1) != true)
329      ++failures;
330
331   i3 += 5;
332   if ((i3 == i2) != true)
333      ++failures;
334
335   i3 -= 5;
336   if ((i3 == i1) != true)
337      ++failures;
338
339   if (i3 + 5 != i2)
340      ++failures;
341
342   if (5 + i3 != i2)
343      ++failures;
344
345   if (i2 - 5 != i3)
346      ++failures;
347
348   if (i1[0] != 1)
349      ++failures;
350
351   i1[4] = 9;
352   if (i2[-1] != 9)
353      ++failures;
354   i1[4] = 5;
355
356   i1[2] = 9;
357   if (i2[-3] != 9)
358      ++failures;
359   i1[2] = 3;
360
361   std::vector<int>::const_iterator ci1(v.begin());
362   if (*ci1 != 1)
363      ++failures;
364
365   ++ci1;
366   if (*ci1 != 2)
367      ++failures;
368
369   if (*ci1++ != 2)
370      ++failures;
371   if (*ci1 != 3)
372      ++failures;
373
374   ++ ++ci1;
375   if (*ci1 != 5)
376      ++failures;
377
378   --ci1;
379   if (*ci1 != 4)
380      ++failures;
381
382   if (*ci1-- != 4)
383      ++failures;
384   if (*ci1 != 3)
385      ++failures;
386
387   -- --ci1;
388   if (*ci1 != 1)
389      ++failures;
390
391   std::vector<int>::const_iterator ci2;
392   ci2 = v.end();
393   std::iterator_traits<std::vector<int>::const_iterator>::difference_type d2;
394   d2 = ci2 - ci1;
395   if (d2 != 5)
396      ++failures;
397
398   std::iterator_traits<std::vector<int>::const_iterator>::value_type v2;
399   v2 = ci1[0];
400   if (v2 != 1)
401      ++failures;
402
403   std::iterator_traits<std::vector<int>::const_iterator>::reference
404      r2(ci1[0]);
405   if (r2 != 1)
406      ++failures;
407
408   if ((ci1 != ci2) != true)
409      ++failures;
410   if ((ci1 == ci2) != false)
411      ++failures;
412   if ((ci1 <  ci2) != true)
413      ++failures;
414   if ((ci1 >  ci2) != false)
415      ++failures;
416   if ((ci1 <= ci2) != true)
417      ++failures;
418   if ((ci1 >= ci2) != false)
419      ++failures;
420
421   std::vector<int>::const_iterator ci3;
422   ci3 = ci1;
423   if ((ci3 == ci1) != true)
424      ++failures;
425
426   ci3 += 5;
427   if ((ci3 == ci2) != true)
428      ++failures;
429
430   ci3 -= 5;
431   if ((ci3 == ci1) != true)
432      ++failures;
433
434   if (ci3 + 5 != ci2)
435      ++failures;
436
437   if (5 + ci3 != ci2)
438      ++failures;
439
440   if (ci2 - 5 != ci3)
441      ++failures;
442
443   if (ci1[2] != 3)
444      ++failures;
445
446   if (ci2[-1] != 5)
447      ++failures;
448
449   // iterator to const_iterator
450   std::vector<int>::const_iterator ci4(i1);
451   if ((ci4 == i1) != true)
452      ++failures;
453   if ((ci4 != i1) != false)
454      ++failures;
455   if ((ci4 < i1)  != false)
456     ++failures;
457   if ((ci4 > i1)  != false)
458     ++failures;
459   if ((ci4 <= i1) != true)
460     ++failures;
461   if ((ci4 >= i1) != true)
462     ++failures;
463   ci4 = i2;
464   if ((i2 == ci4) != true)
465     ++failures;
466   if ((i2 < ci4)  != false)
467     ++failures;
468   if ((i2 > ci4)  != false)
469     ++failures;
470   if ((i2 <= ci4) != true)
471     ++failures;
472   if ((i2 >= ci4) != true)
473     ++failures;
474
475   const std::vector<int> cv(v);
476   std::vector<int>::const_iterator ci5(cv.begin());
477   if (ci5[0] != 1)
478      ++failures;
479
480   std::vector<std::string> vs;
481   vs.push_back(std::string("abc"));
482   std::vector<std::string>::iterator ivs(vs.begin());
483   if (ivs->c_str()[1] != 'b')
484      ++failures;
485
486   return failures;
487}
488
489int
490reverse_stuff()
491{
492   int failures(0);
493
494   std::string s("abcde");
495
496   std::string::reverse_iterator ri(s.rbegin());
497   if (*ri != 'e')
498      ++failures;
499
500   std::iterator_traits<std::string::reverse_iterator>::difference_type d;
501   d = s.rend() - ri;
502   if (d != 5)
503      ++failures;
504
505   const std::string cs("abcde");
506   std::string::const_reverse_iterator cri(cs.rend());
507   if (cri - 5 != cs.rbegin())
508      ++failures;
509
510   return failures;
511}
512
513// the following should be compiler errors
514// flag runtime errors in case they slip through the compiler
515int
516wrong_stuff()
517{
518   int failures(0);
519
520#ifdef ITER24_F1
521   extern void f(std::vector<std::string*>::iterator);
522   std::vector<std::string*> vs[2];
523   f(vs);                       // address of array is not an iterator
524   failures++;
525#endif
526
527#ifdef ITER24_F2
528   std::string s;
529   char *i = s.begin();         // begin() doesn't return a pointer
530   failures++;
531#endif
532
533#ifdef ITER24_F3
534   std::string::const_iterator ci;
535   std::string::iterator i;
536   if (i - ci)                  // remove const_ is a warning
537      i++;
538   // failures++;  only a warning
539#endif
540
541#ifdef ITER24_F4
542   std::vector<char>::iterator iv;
543   std::string::iterator is(iv);// vector<char> is not string
544   failures++;
545#endif
546
547#ifdef ITER24_F5
548   std::vector<char>::iterator iv;
549   std::string::iterator is;
550   if (iv == is)                // vector<char> is not string
551      ++iv;
552   failures++;
553#endif
554
555#ifdef ITER24_F6
556   std::vector<char>::const_iterator ci;
557   std::vector<char>::iterator i = ci;  // remove const_ is a warning
558   ++i;
559   // failures++; only a warning
560#endif
561
562#ifdef ITER24_F7
563   std::vector<int> v(1);
564   std::vector<int>::const_iterator ci(v.begin());
565   *ci = 1;                     // cannot assign through const_iterator
566   failures++;
567#endif
568
569#ifdef ITER24_F8
570   std::vector<const int> v(1);
571   std::vector<const int>::reference r(v.begin()[0]);
572   r = 1;                       // cannot assign through reference to const
573   failures++;
574#endif
575
576   return failures;
577}
578
579// libstdc++/6642
580int
581test6642()
582{
583   std::string s;
584   std::string::iterator it = s.begin();
585   std::string::const_iterator cit = s.begin();
586
587   return it - cit;
588}
589
590int
591main()
592{
593   int failures(0);
594
595   failures += string_stuff();
596
597   failures += vector_stuff();
598
599   failures += reverse_stuff();
600
601   failures += wrong_stuff();
602
603   failures += test6642();
604
605   VERIFY(failures == 0);
606   return 0;
607}
608