1 // array TR1 header
2 #pragma once
3 #ifndef _ARRAY_
4 #define _ARRAY_
5 #ifndef RC_INVOKED
6 #include <algorithm>
7 #include <iterator>
8
9  #pragma pack(push,_CRT_PACKING)
10  #pragma warning(push,3)
11  #pragma warning(disable: 4284)
12  #pragma warning(disable: 4996)
13
14 _STD_BEGIN
15     namespace tr1 {    // TR1 additions
16
17 _CRTIMP2_PURE __declspec(noreturn) void __CLRCALL_PURE_OR_CDECL _Xoutrange();
18
19     // static_assert
20 template<bool expr>
21     struct _Assert_failed;
22 template<>
23     struct _Assert_failed<true>
24     {    // specialize for true
25     };
26
27  #define _Assert_static(EXPR)    \
28     enum {static_assert_failure = sizeof (_Assert_failed<(bool)(EXPR)>)}
29
30 template<class _Ty,
31     size_t _Size>
32     class array;
33
34         // TEMPLATE CLASS _Array_const_iterator
35 template<class _Ty,
36     size_t _Size>
37     class _Array_const_iterator
38         : public _Iterator_base_universal
39     {    // iterator for nonmutable array
40 public:
41     typedef _Array_const_iterator<_Ty, _Size> _Myiter;
42     typedef array<_Ty, _Size> _Myarr;
43     typedef random_access_iterator_tag iterator_category;
44
45     typedef typename _Myarr::pointer _Tptr;
46     typedef typename _Myarr::value_type value_type;
47     typedef typename _Myarr::size_type size_type;
48     typedef typename _Myarr::difference_type difference_type;
49     typedef typename _Myarr::const_pointer pointer;
50     typedef typename _Myarr::const_reference reference;
51
52     _Array_const_iterator()
53         {    // construct with null pointer
54         _Ptr = 0;
55         _Idx = 0;
56         }
57
58     _Array_const_iterator(_Tptr _Parg, size_t _Off)
59         {    // construct with pointer and offset
60         _Ptr = _Parg;
61         _Idx = _Off;
62         }
63
64     enum {_EEN_SIZE = _Size};    // helper for expression evaluator
65
66     typedef _Range_checked_iterator_tag _Checked_iterator_category;
67     typedef value_type _Inner_type;
68     typedef pointer _Checked_iterator_base_type;
69
70     _Checked_iterator_base_type _Checked_iterator_base() const
71         {    // get unchecked version of iterator
72         return (_Ptr + _Idx);
73         }
74
75     void _Checked_iterator_assign_from_base(_Checked_iterator_base_type _Iter)
76         {    // resync with unchecked version
77         _Idx = _Iter - _Ptr;
78         }
79
80     reference operator*() const
81         {    // return designated object
82  #if _HAS_ITERATOR_DEBUGGING
83         if (_Ptr == 0
84             || _Size <= _Idx)
85             {    // report error
86             _DEBUG_ERROR("array iterator not dereferencable");
87             _SCL_SECURE_OUT_OF_RANGE;
88             }
89  #endif /* _HAS_ITERATOR_DEBUGGING */
90
91         _SCL_SECURE_VALIDATE(_Ptr != 0);
92         _SCL_SECURE_VALIDATE_RANGE(_Idx < _Size);
93
94         return (_Ptr[_Idx]);
95         }
96
97     pointer operator->() const
98         {    // return pointer to class object
99         return (&**this);
100         }
101
102     _Myiter& operator++()
103         {    // preincrement
104  #if _HAS_ITERATOR_DEBUGGING
105         if (_Ptr == 0
106             || _Size <= _Idx)
107             {    // report error
108             _DEBUG_ERROR("array iterator not incrementable");
109             _SCL_SECURE_OUT_OF_RANGE;
110             }
111  #endif /* _HAS_ITERATOR_DEBUGGING */
112
113         _SCL_SECURE_VALIDATE(_Ptr != 0);
114         _SCL_SECURE_VALIDATE_RANGE(_Idx < _Size);
115
116         ++_Idx;
117         return (*this);
118         }
119
120     _Myiter operator++(int)
121         {    // postincrement
122         _Myiter _Tmp = *this;
123         ++*this;
124         return (_Tmp);
125         }
126
127     _Myiter& operator--()
128         {    // predecrement
129  #if _HAS_ITERATOR_DEBUGGING
130         if (_Ptr == 0
131             || _Idx <= 0)
132             {    // report error
133             _DEBUG_ERROR("array iterator not decrementable");
134             _SCL_SECURE_OUT_OF_RANGE;
135             }
136  #endif /* _HAS_ITERATOR_DEBUGGING */
137
138         _SCL_SECURE_VALIDATE(_Ptr != 0);
139         _SCL_SECURE_VALIDATE_RANGE(0 < _Idx);
140
141         --_Idx;
142         return (*this);
143         }
144
145     _Myiter operator--(int)
146         {    // postdecrement
147         _Myiter _Tmp = *this;
148         --*this;
149         return (_Tmp);
150         }
151
152     _Myiter& operator+=(difference_type _Off)
153         {    // increment by integer
154         _Idx += _Off;
155         return (*this);
156         }
157
158     _Myiter operator+(difference_type _Off) const
159         {    // return this + integer
160         _Myiter _Tmp = *this;
161         return (_Tmp += _Off);
162         }
163
164     _Myiter& operator-=(difference_type _Off)
165         {    // decrement by integer
166         return (*this += -_Off);
167         }
168
169     _Myiter operator-(difference_type _Off) const
170         {    // return this - integer
171         _Myiter _Tmp = *this;
172         return (_Tmp -= _Off);
173         }
174
175     difference_type operator-(const _Myiter& _Right) const
176         {    // return difference of iterators
177         _Compat(_Right);
178         return (_Idx < _Right._Idx
179             ? -(difference_type)(_Right._Idx - _Idx)
180             : (difference_type)_Idx - _Right._Idx);
181         }
182
183     reference operator[](difference_type _Off) const
184         {    // subscript
185         return (*(*this + _Off));
186         }
187
188     bool operator==(const _Myiter& _Right) const
189         {    // test for iterator equality
190         _Compat(_Right);
191         return (_Idx == _Right._Idx);
192         }
193
194     bool operator!=(const _Myiter& _Right) const
195         {    // test for iterator inequality
196         return (!(*this == _Right));
197         }
198
199     bool operator<(const _Myiter& _Right) const
200         {    // test if this < _Right
201         _Compat(_Right);
202         return (_Idx < _Right._Idx);
203         }
204
205     bool operator>(const _Myiter& _Right) const
206         {    // test if this > _Right
207         return (_Right < *this);
208         }
209
210     bool operator<=(const _Myiter& _Right) const
211         {    // test if this <= _Right
212         return (!(_Right < *this));
213         }
214
215     bool operator>=(const _Myiter& _Right) const
216         {    // test if this >= _Right
217         return (!(*this < _Right));
218         }
219
220     void _Compat(const _Myiter& _Right) const
221         {    // test for compatible iterator pair
222  #if _HAS_ITERATOR_DEBUGGING
223         if (_Ptr != _Right._Ptr)
224             {    // report error
225             _DEBUG_ERROR("array iterators incompatible");
226             _SCL_SECURE_INVALID_ARGUMENT;
227             }
228  #endif /* _HAS_ITERATOR_DEBUGGING */
229
230         _SCL_SECURE_VALIDATE_RANGE(_Ptr == _Right._Ptr);
231         }
232
233     _Tptr _Ptr;    // beginning of array
234     size_t _Idx;    // offset into array
235     };
236
237 template<class _Ty,
238     size_t _Size> inline
239     _Array_const_iterator<_Ty, _Size> operator+(
240         typename _Array_const_iterator<_Ty, _Size>::difference_type _Off,
241         _Array_const_iterator<_Ty, _Size> _Next)
242     {    // add offset to iterator
243     return (_Next += _Off);
244     }
245
246         // TEMPLATE CLASS _Array_iterator
247 template<class _Ty,
248     size_t _Size>
249     class _Array_iterator
250         : public _Array_const_iterator<_Ty, _Size>
251     {    // iterator for mutable array
252 public:
253     typedef _Array_iterator<_Ty, _Size> _Myiter;
254     typedef _Array_const_iterator<_Ty, _Size> _Mybase;
255     typedef array<_Ty, _Size> _Myarr;
256     typedef random_access_iterator_tag iterator_category;
257
258     typedef typename _Myarr::value_type value_type;
259     typedef typename _Myarr::size_type size_type;
260     typedef typename _Myarr::difference_type difference_type;
261     typedef typename _Myarr::pointer pointer;
262     typedef typename _Myarr::reference reference;
263
264     _Array_iterator()
265         {    // construct with null pointer
266         }
267
268     _Array_iterator(pointer _Parg, size_t _Off)
269         : _Mybase(_Parg, _Off)
270         {    // construct with pointer and offset
271         }
272
273     enum {_EEN_SIZE = _Size};    // helper for expression evaluator
274
275     typedef _Range_checked_iterator_tag _Checked_iterator_category;
276     typedef _Ty _Inner_type;
277     typedef pointer _Checked_iterator_base_type;
278
279     _Checked_iterator_base_type _Checked_iterator_base() const
280         {    // get unchecked version of iterator
281         return (this->_Ptr + this->_Idx);
282         }
283
284     void _Checked_iterator_assign_from_base(_Checked_iterator_base_type _Iter)
285         {    // resync with unchecked version
286         this->_Idx = _Iter - this->_Ptr;
287         }
288
289     reference operator*() const
290         {    // return designated object
291         return ((reference)**(_Mybase *)this);
292         }
293
294     pointer operator->() const
295         {    // return pointer to class object
296         return (&**this);
297         }
298
299     _Myiter& operator++()
300         {    // preincrement
301         ++*(_Mybase *)this;
302         return (*this);
303         }
304
305     _Myiter operator++(int)
306         {    // postincrement
307         _Myiter _Tmp = *this;
308         ++*this;
309         return (_Tmp);
310         }
311
312     _Myiter& operator--()
313         {    // predecrement
314         --*(_Mybase *)this;
315         return (*this);
316         }
317
318     _Myiter operator--(int)
319         {    // postdecrement
320         _Myiter _Tmp = *this;
321         --*this;
322         return (_Tmp);
323         }
324
325     _Myiter& operator+=(difference_type _Off)
326         {    // increment by integer
327         *(_Mybase *)this += _Off;
328         return (*this);
329         }
330
331     _Myiter operator+(difference_type _Off) const
332         {    // return this + integer
333         _Myiter _Tmp = *this;
334         return (_Tmp += _Off);
335         }
336
337     _Myiter& operator-=(difference_type _Off)
338         {    // decrement by integer
339         return (*this += -_Off);
340         }
341
Lines 342 ... 351 are skipped.
352
353     reference operator[](difference_type _Off) const
354         {    // subscript
355         return (*(*this + _Off));
356         }
357     };
358
359 template<class _Ty,
360     size_t _Size> inline
361     _Array_iterator<_Ty, _Size> operator+(
362         typename _Array_iterator<_Ty, _Size>::difference_type _Off,
363         _Array_iterator<_Ty, _Size> _Next)
364     {    // add offset to iterator
365     return (_Next += _Off);
366     }
367
368     // TEMPLATE CLASS array
369 template<class _Ty,
370     size_t _Size>
371     class array
372     {    // fixed size array of values
373 public:
374     enum {_EEN_SIZE = _Size};    // helper for expression evaluator
375
376     typedef array<_Ty, _Size> _Myt;
377     typedef _Ty value_type;
378     typedef size_t size_type;
379     typedef ptrdiff_t difference_type;
380     typedef _Ty *pointer;
381     typedef const _Ty *const_pointer;
382     typedef _Ty& reference;
383     typedef const _Ty& const_reference;
384
385     typedef _Array_iterator<_Ty, _Size> iterator;
386     typedef _Array_const_iterator<_Ty, _Size> const_iterator;
387
388     typedef std::reverse_iterator<iterator> reverse_iterator;
389     typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
390
391     void assign(const _Ty& _Value)
392         {    // assign value to all elements
393         std::fill_n(_Elems, _Size, _Value);
394         }
395
396     void swap(_Myt& _Other)
397         {    // swap contents with _Other
398         std::swap_ranges(_Other.begin(), _Other.end(), begin());
399         }
400
401     iterator begin()
402         {    // return iterator for beginning of mutable sequence
403         return (iterator(&_Elems[0], 0));
404         }
405
406     const_iterator begin() const
407         {    // return iterator for beginning of nonmutable sequence
408         return (const_iterator((pointer)&_Elems[0], 0));
409         }
410
411     iterator end()
412         {    // return iterator for end of mutable sequence
413         return (iterator(&_Elems[0], _Size));
414         }
415
416     const_iterator end() const
417         {    // return iterator for beginning of nonmutable sequence
418         return (const_iterator((pointer)&_Elems[0], _Size));
419         }
420
421     reverse_iterator rbegin()
422         {    // return iterator for beginning of reversed mutable sequence
423         return (reverse_iterator(end()));
424         }
425
426     const_reverse_iterator rbegin() const
427         {    // return iterator for beginning of reversed nonmutable sequence
428         return (const_reverse_iterator(end()));
429         }
430
431     reverse_iterator rend()
432         {    // return iterator for end of reversed mutable sequence
433         return (reverse_iterator(begin()));
434         }
435
436     const_reverse_iterator rend() const
437         {    // return iterator for end of reversed nonmutable sequence
438         return (const_reverse_iterator(begin()));
439         }
440
441     size_type size() const
442         {    // return length of sequence
443         return (_Size);
444         }
445
446     size_type max_size() const
447         {    // return maximum possible length of sequence
448         return (_Size);
449         }
450
451     bool empty() const
452         {    // test if sequence is empty
453         return (_Size == 0);
454         }
455
456     reference at(size_type _Pos)
457         {    // subscript mutable sequence with checking
458         if (_Size <= _Pos)
459             _Xoutrange();
460         return (_Elems[_Pos]);
461         }
462
463     const_reference at(size_type _Pos) const
464         {    // subscript nonmutable sequence with checking
465         if (_Size <= _Pos)
466             _Xoutrange();
467         return (_Elems[_Pos]);
468         }
469
470     reference operator[](size_type _Pos)
471         {    // subscript mutable sequence
472  #if _HAS_ITERATOR_DEBUGGING
473         if (_Size <= _Pos)
474             _DEBUG_ERROR("array subscript out of range");
475  #endif /* _HAS_ITERATOR_DEBUGGING */
476
477         _SCL_SECURE_VALIDATE_RANGE(_Pos < _Size);
478
479         return (_Elems[_Pos]);
480         }
481
482     const_reference operator[](size_type _Pos) const
483         {    // subscript nonmutable sequence
484  #if _HAS_ITERATOR_DEBUGGING
485         if (_Size <= _Pos)
486             _DEBUG_ERROR("array subscript out of range");
487  #endif /* _HAS_ITERATOR_DEBUGGING */
488
489         _SCL_SECURE_VALIDATE_RANGE(_Pos < _Size);
490
491         return (_Elems[_Pos]);
492         }
493
494     reference front()
495         {    // return first element of mutable sequence
496  #if _HAS_ITERATOR_DEBUGGING
497         if (_Size == 0)
498             _DEBUG_ERROR("array<T, 0>::front() invalid");
499  #endif /* _HAS_ITERATOR_DEBUGGING */
500
501         _SCL_SECURE_VALIDATE_RANGE(0 < _Size);
502
503         return (_Elems[0]);
504         }
505
506     const_reference front() const
507         {    // return first element of nonmutable sequence
508  #if _HAS_ITERATOR_DEBUGGING
509         if (_Size == 0)
510             _DEBUG_ERROR("array<T, 0>::front() invalid");
511  #endif /* _HAS_ITERATOR_DEBUGGING */
512
513         _SCL_SECURE_VALIDATE_RANGE(0 < _Size);
514
515         return (_Elems[0]);
516         }
517
518     reference back()
519         {    // return last element of mutable sequence
520  #if _HAS_ITERATOR_DEBUGGING
521         if (_Size == 0)
522             _DEBUG_ERROR("array<T, 0>::back() invalid");
523  #endif /* _HAS_ITERATOR_DEBUGGING */
524
525         _SCL_SECURE_VALIDATE_RANGE(0 < _Size);
526
527         return (_Elems[_Size - 1]);
528         }
529
530     const_reference back() const
531         {    // return last element of nonmutable sequence
532  #if _HAS_ITERATOR_DEBUGGING
533         if (_Size == 0)
534             _DEBUG_ERROR("array<T, 0>::back() invalid");
535  #endif /* _HAS_ITERATOR_DEBUGGING */
536
537         _SCL_SECURE_VALIDATE_RANGE(0 < _Size);
538
539         return (_Elems[_Size - 1]);
540         }
541
542     _Ty *data()
543         {    // return pointer to mutable data array
544         return (_Elems);
545         }
546
547     const _Ty *data() const
548         {    // return pointer to nonmutable data array
549         return (_Elems);
550         }
551
552     _Ty _Elems[_Size == 0 ? 1 : _Size];
553     };
554
555 template<class _Ty,
556     size_t _Size>
557     void swap(array<_Ty,_Size>& _Left,
558         array<_Ty,_Size>& _Right)
559     {    // swap arrays
560     return (_Left.swap(_Right));
561     }
562
563 template<class _Ty,
564     size_t _Size>
565     bool operator==(const array<_Ty,_Size>& _Left,
566         const array<_Ty,_Size>& _Right)
567     {    // test for array equality
568     return (std::equal(_Left.begin(), _Left.end(), _Right.begin()));
569     }
570
571 template<class _Ty,
572     size_t _Size>
573     bool operator!=(const array<_Ty,_Size>& _Left,
574         const array<_Ty,_Size>& _Right)
575     {    // test for array inequality
576     return (!(_Left == _Right));
577     }
578
579 template<class _Ty,
580     size_t _Size>
581     bool operator<(const array<_Ty,_Size>& _Left,
582         const array<_Ty,_Size>& _Right)
583     {    // test if _Left < _Right for arrays
584     return (std::lexicographical_compare(_Left.begin(), _Left.end(),
585         _Right.begin(), _Right.end()));
586     }
587
588 template<class _Ty,
589     size_t _Size>
590     bool operator>(const array<_Ty,_Size>& _Left,
591         const array<_Ty,_Size>& _Right)
592     {    // test if _Left > _Right for arrays
593     return (_Right < _Left);
594     }
595
596 template<class _Ty,
597     size_t _Size>
598     bool operator<=(const array<_Ty,_Size>& _Left,
599     const array<_Ty,_Size>& _Right)
600     {    // test if _Left <= _Right for arrays
601     return (!(_Right < _Left));
602     }
603
604 template<class _Ty,
605     size_t _Size>
606     bool operator>=(const array<_Ty,_Size>& _Left,
607     const array<_Ty,_Size>& _Right)
608     {    // test if _Left >= _Right for arrays
609     return (!(_Left < _Right));
610     }
611
612  #if _HAS_TR1
613     // TUPLE INTERFACE TO array
614 template<class _Tuple>
615     struct tuple_size;
616
617 template<int _Idx,
618     class _Tuple>
619     struct tuple_element;
620
621 template<class _Ty,
622     size_t _Size>
623     struct tuple_size<array<_Ty, _Size> >
624     {    // struct to determine number of elements in array
625     static const int value = _Size;
626     };
627
628 template<int _Idx,
629     class _Ty,
630     size_t _Size>
631     struct tuple_element<_Idx, array<_Ty, _Size> >
632     {    // struct to determine type of element _Idx in array
633     typedef _Ty type;
634     };
635
636 template<int _Idx,
637     class _Ty,
638     size_t _Size>
639     _Ty& get(array<_Ty, _Size>& _Arr)
640     {    // return element at _Idx in array _Arr
641     _Assert_static(0 <= _Idx && _Idx < _Size);
642     return (_Arr[_Idx]);
643     }
644
645 template<int _Idx,
646     class _Ty,
647     size_t _Size>
648     const _Ty& get(const array<_Ty, _Size>& _Arr)
649     {    // return element at _Idx in array _Arr
650     _Assert_static(0 <= _Idx && _Idx < _Size);
651     return (_Arr[_Idx]);
652     }
653  #endif /* _HAS_TR1 */
654
655     }    // namespace tr1
656
657     // array implements a performant swap if its elements do
658 template<class _Ty,
659     size_t _Size>
660     class _Move_operation_category<tr1::array<_Ty, _Size> >
661     {
662 public:
663     typedef typename _Move_operation_category<_Ty>::_Move_cat _Move_cat;
664     };
665
666 _STD_END
667  #pragma warning(default: 4996)
668  #pragma warning(default: 4284)
669  #pragma warning(pop)
670  #pragma pack(pop)
671 #endif /* RC_INVOKED */
672 #endif /* _ARRAY_ */
673
674 /*
675  * Copyright (c) 1992-2008 by P.J. Plauger.  ALL RIGHTS RESERVED.
676  * Consult your license regarding permissions and restrictions.
677 V5.05:0009 */
678