forked from duneroadrunner/SaferCPlusPlus
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmsemsevector.h
4258 lines (3964 loc) · 230 KB
/
msemsevector.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
// Copyright (c) 2015 Noah Lopez
// Use, modification, and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#pragma once
#ifndef MSEMSEVECTOR_H
#define MSEMSEVECTOR_H
/*compiler specific defines*/
#ifdef _MSC_VER
#if (1700 > _MSC_VER)
#define MSVC2010_COMPATIBLE 1
#endif /*(1700 > _MSC_VER)*/
#if (1900 > _MSC_VER)
#define MSVC2013_COMPATIBLE 1
#endif /*(1900 > _MSC_VER)*/
#else /*_MSC_VER*/
#if (defined(__GNUC__) || defined(__GNUG__))
#define GPP_COMPATIBLE 1
#if ((5 > __GNUC__) && (!defined(__clang__)))
#define GPP4P8_COMPATIBLE 1
#endif /*((5 > __GNUC__) && (!defined(__clang__)))*/
#endif
#endif /*_MSC_VER*/
//define MSE_MSEVECTOR_USE_MSE_PRIMITIVES 1
#ifdef MSE_MSEVECTOR_USE_MSE_PRIMITIVES
#include "mseprimitives.h"
#endif // MSE_MSEVECTOR_USE_MSE_PRIMITIVES
#include "msemsearray.h"
#include <vector>
#include <assert.h>
#include <memory>
#include <unordered_map>
#include <functional>
#include <climits> // ULONG_MAX
#include <stdexcept>
#ifdef MSE_SAFER_SUBSTITUTES_DISABLED
#define MSE_MSTDVECTOR_DISABLED
#endif /*MSE_SAFER_SUBSTITUTES_DISABLED*/
#ifndef NDEBUG
#ifndef MSE_SUPPRESS_MSTD_VECTOR_CHECK_USE_AFTER_FREE
#define MSE_MSTD_VECTOR_CHECK_USE_AFTER_FREE
#endif // !MSE_SUPPRESS_MSTD_VECTOR_CHECK_USE_AFTER_FREE
#endif // !NDEBUG
#ifdef MSE_CUSTOM_THROW_DEFINITION
#include <iostream>
#define MSE_THROW(x) MSE_CUSTOM_THROW_DEFINITION(x)
#else // MSE_CUSTOM_THROW_DEFINITION
#define MSE_THROW(x) throw(x)
#endif // MSE_CUSTOM_THROW_DEFINITION
namespace mse {
#ifdef MSE_MSEVECTOR_USE_MSE_PRIMITIVES
typedef mse::CSize_t msev_size_t;
typedef mse::CInt msev_int;
typedef bool msev_bool; // no added safety benefit to using mse::CBool in this case
#define msev_as_a_size_t as_a_size_t
#else // MSE_MSEVECTOR_USE_MSE_PRIMITIVES
#ifndef MSE_MSEVECTOR_BASE_INTEGER_TYPE
#if SIZE_MAX <= UINT_MAX
#define MSE_MSEVECTOR_BASE_INTEGER_TYPE int
#else // SIZE_MAX <= INT_MAX
#if SIZE_MAX <= ULONG_MAX
#define MSE_MSEVECTOR_BASE_INTEGER_TYPE long int
#else // SIZE_MAX <= ULONG_MAX
#define MSE_MSEVECTOR_BASE_INTEGER_TYPE long long int
#endif // SIZE_MAX <= ULONG_MAX
#endif // SIZE_MAX <= INT_MAX
#endif // !MSE_MSEVECTOR_BASE_INTEGER_TYPE
typedef size_t msev_size_t;
typedef MSE_MSEVECTOR_BASE_INTEGER_TYPE msev_int;
typedef bool msev_bool;
typedef size_t msev_as_a_size_t;
#endif // MSE_MSEVECTOR_USE_MSE_PRIMITIVES
class nii_vector_range_error : public std::range_error {
public:
using std::range_error::range_error;
};
class nii_vector_null_dereference_error : public std::logic_error {
public:
using std::logic_error::logic_error;
};
class msevector_range_error : public std::range_error { public:
using std::range_error::range_error;
};
class msevector_null_dereference_error : public std::logic_error { public:
using std::logic_error::logic_error;
};
/* msev_pointer behaves similar to native pointers. It's a bit safer in that it initializes to
nullptr by default and checks for attempted dereference of null pointers. */
template<typename _Ty>
class msev_pointer {
public:
msev_pointer() : m_ptr(nullptr) {}
msev_pointer(_Ty* ptr) : m_ptr(ptr) {}
//msev_pointer(const msev_pointer<_Ty>& src) : m_ptr(src.m_ptr) {}
template<class _Ty2, class = typename std::enable_if<
std::is_same<_Ty2, _Ty>::value || ((!std::is_const<_Ty2>::value) && std::is_same<const _Ty2, _Ty>::value)
, void>::type>
msev_pointer(const msev_pointer<_Ty2>& src) : m_ptr(src.m_ptr) {}
_Ty& operator*() const {
#ifndef MSE_DISABLE_MSEAR_POINTER_CHECKS
if (nullptr == m_ptr) { MSE_THROW(msevector_null_dereference_error("attempt to dereference null pointer - mse::msev_pointer")); }
#endif /*MSE_DISABLE_MSEAR_POINTER_CHECKS*/
return (*m_ptr);
}
_Ty* operator->() const {
#ifndef MSE_DISABLE_MSEAR_POINTER_CHECKS
if (nullptr == m_ptr) { MSE_THROW(msevector_null_dereference_error("attempt to dereference null pointer - mse::msev_pointer")); }
#endif /*MSE_DISABLE_MSEAR_POINTER_CHECKS*/
return m_ptr;
}
msev_pointer<_Ty>& operator=(_Ty* ptr) {
m_ptr = ptr;
return (*this);
}
bool operator==(const msev_pointer _Right_cref) const { return (_Right_cref.m_ptr == m_ptr); }
bool operator!=(const msev_pointer _Right_cref) const { return (!((*this) == _Right_cref)); }
//bool operator==(const _Ty* _Right_cref) const { return (_Right_cref == m_ptr); }
//bool operator!=(const _Ty* _Right_cref) const { return (!((*this) == _Right_cref)); }
bool operator!() const { return (!m_ptr); }
operator bool() const { return (m_ptr != nullptr); }
explicit operator _Ty*() const { return m_ptr; }
void not_async_shareable_tag() const {} /* Indication that this type is not eligible to be shared between threads. */
_Ty* m_ptr;
};
#ifndef _XSTD
#define _XSTD ::std::
#endif /*_XSTD*/
template<class _Ty, _Ty _Val>
struct integral_constant
{ // convenient template for integral constant types
static const _Ty value = _Val;
typedef _Ty value_type;
typedef integral_constant<_Ty, _Val> type;
operator value_type() const
{ // return stored value
return (value);
}
};
template<class _Iter>
struct _mse_Is_iterator
: public integral_constant<bool, !std::is_integral<_Iter>::value>
{ // tests for reasonable iterator candidate
};
template<typename _InIter>
using _mse_RequireInputIter = typename std::enable_if<
std::is_convertible<typename std::iterator_traits<_InIter>::iterator_category, std::input_iterator_tag>::value
//_mse_Is_iterator<_InIter>::value
>::type;
template<class T, class EqualTo>
struct HasOrInheritsLessThanOperator_msemsevector_impl
{
template<class U, class V>
static auto test(U*) -> decltype(std::declval<U>() < std::declval<V>(), bool(true));
template<typename, typename>
static auto test(...)->std::false_type;
using type = typename std::is_same<bool, decltype(test<T, EqualTo>(0))>::type;
};
template<class T, class EqualTo = T>
struct HasOrInheritsLessThanOperator_msemsevector : HasOrInheritsLessThanOperator_msemsevector_impl<
typename std::remove_reference<T>::type, typename std::remove_reference<EqualTo>::type>::type {};
template<class _Ty, class _A/* = std::allocator<_Ty>*/, class _TStateMutex/* = default_state_mutex*/>
class nii_vector;
namespace us {
template<class _Ty, class _A = std::allocator<_Ty>, class _TStateMutex = default_state_mutex>
class msevector;
}
/* Following are a bunch of template (iterator) classes that, organizationally, should be members of nii_vector<>. (And they
used to be.) However, being a member of nii_vector<> makes them "dependent types", and dependent types do not participate
in automatic template parameter type deduction. So we had to haul them here outside of nii_vector<>. */
/* The reason we specify the default parameter in the definition instead of this forward declaration is that there seems to be a
bug in clang (3.8.0) such that if we don't specify the default parameter in the definition it seems to subsequently behave as if
one were never specified. g++ and msvc don't seem to have the same issue. */
template<typename _TVectorPointer, class _Ty, class _A, class _TStateMutex, class/* = typename std::enable_if<(!std::is_base_of<XScopeTagBase, _TVectorPointer>::value), void>::type*/>
class Tnii_vector_ss_iterator_type;
/* Tnii_vector_ss_const_iterator_type is a bounds checked const_iterator. */
template<typename _TVectorConstPointer, class _Ty, class _A = std::allocator<_Ty>, class _TStateMutex = default_state_mutex, class = typename std::enable_if<(!std::is_base_of<XScopeTagBase, _TVectorConstPointer>::value), void>::type>
class Tnii_vector_ss_const_iterator_type : public random_access_const_iterator_base<_Ty> {
public:
typedef random_access_const_iterator_base<_Ty> base_class;
typedef typename base_class::iterator_category iterator_category;
typedef typename base_class::value_type value_type;
typedef typename base_class::difference_type difference_type;
typedef typename base_class::pointer pointer;
typedef typename base_class::reference reference;
typedef const pointer const_pointer;
typedef const reference const_reference;
//template<class = typename std::enable_if<std::is_default_constructible<_TVectorConstPointer>::value, void>::type>
template<class _TVectorConstPointer2 = _TVectorConstPointer, class = typename std::enable_if<(std::is_same<_TVectorConstPointer2, _TVectorConstPointer>::value) && (std::is_default_constructible<_TVectorConstPointer>::value), void>::type>
Tnii_vector_ss_const_iterator_type() {}
Tnii_vector_ss_const_iterator_type(const _TVectorConstPointer& owner_cptr) : m_owner_cptr(owner_cptr) {}
Tnii_vector_ss_const_iterator_type(_TVectorConstPointer&& owner_cptr) : m_owner_cptr(std::forward<decltype(owner_cptr)>(owner_cptr)) {}
Tnii_vector_ss_const_iterator_type(Tnii_vector_ss_const_iterator_type&& src) = default;
Tnii_vector_ss_const_iterator_type(const Tnii_vector_ss_const_iterator_type& src) = default;
template<class _Ty2, class = typename std::enable_if<std::is_convertible<_Ty2, _TVectorConstPointer>::value, void>::type>
Tnii_vector_ss_const_iterator_type(const Tnii_vector_ss_const_iterator_type<_Ty2, _Ty, _A, _TStateMutex>& src) : m_owner_cptr(src.target_container_ptr()), m_index(src.position()) {}
template<class _Ty2, class = typename std::enable_if<std::is_convertible<_Ty2, _TVectorConstPointer>::value, void>::type>
Tnii_vector_ss_const_iterator_type(const Tnii_vector_ss_iterator_type<_Ty2, _Ty, _A, _TStateMutex, void>& src) : m_owner_cptr(src.target_container_ptr()), m_index(src.position()) {}
void assert_valid_index() const {
if (m_owner_cptr->size() < m_index) { MSE_THROW(nii_vector_range_error("invalid index - void assert_valid_index() const - ss_const_iterator_type - nii_vector")); }
}
void reset() { set_to_end_marker(); }
bool points_to_an_item() const {
if (m_owner_cptr->size() > m_index) { return true; }
else {
assert(m_index == m_owner_cptr->size());
return false;
}
}
bool points_to_end_marker() const {
if (false == points_to_an_item()) {
assert(m_index == m_owner_cptr->size());
return true;
}
else { return false; }
}
bool points_to_beginning() const {
if (0 == m_index) { return true; }
else { return false; }
}
/* has_next_item_or_end_marker() is just an alias for points_to_an_item(). */
bool has_next_item_or_end_marker() const { return points_to_an_item(); } //his is
/* has_next() is just an alias for points_to_an_item() that's familiar to java programmers. */
bool has_next() const { return has_next_item_or_end_marker(); }
bool has_previous() const {
return ((1 <= m_owner_cptr->size()) && (!points_to_beginning()));
}
void set_to_beginning() {
m_index = 0;
}
void set_to_end_marker() {
m_index = m_owner_cptr->size();
}
void set_to_next() {
if (points_to_an_item()) {
m_index += 1;
assert(m_owner_cptr->size() >= m_index);
}
else {
MSE_THROW(nii_vector_range_error("attempt to use invalid const_item_pointer - void set_to_next() - Tnii_vector_ss_const_iterator_type - nii_vector"));
}
}
void set_to_previous() {
if (has_previous()) {
m_index -= 1;
}
else {
MSE_THROW(nii_vector_range_error("attempt to use invalid const_item_pointer - void set_to_previous() - Tnii_vector_ss_const_iterator_type - nii_vector"));
}
}
Tnii_vector_ss_const_iterator_type& operator ++() { (*this).set_to_next(); return (*this); }
Tnii_vector_ss_const_iterator_type operator++(int) { Tnii_vector_ss_const_iterator_type _Tmp = *this; (*this).set_to_next(); return (_Tmp); }
Tnii_vector_ss_const_iterator_type& operator --() { (*this).set_to_previous(); return (*this); }
Tnii_vector_ss_const_iterator_type operator--(int) { Tnii_vector_ss_const_iterator_type _Tmp = *this; (*this).set_to_previous(); return (_Tmp); }
void advance(difference_type n) {
auto new_index = msear_int(m_index) + n;
if ((0 > new_index) || (m_owner_cptr->size() < msear_size_t(new_index))) {
MSE_THROW(nii_vector_range_error("index out of range - void advance(difference_type n) - Tnii_vector_ss_const_iterator_type - nii_vector"));
}
else {
m_index = msear_size_t(new_index);
}
}
void regress(difference_type n) { advance(-n); }
Tnii_vector_ss_const_iterator_type& operator +=(difference_type n) { (*this).advance(n); return (*this); }
Tnii_vector_ss_const_iterator_type& operator -=(difference_type n) { (*this).regress(n); return (*this); }
Tnii_vector_ss_const_iterator_type operator+(difference_type n) const {
Tnii_vector_ss_const_iterator_type retval(*this);
retval.advance(n);
return retval;
}
Tnii_vector_ss_const_iterator_type operator-(difference_type n) const { return ((*this) + (-n)); }
difference_type operator-(const Tnii_vector_ss_const_iterator_type &rhs) const {
if (rhs.m_owner_cptr != (*this).m_owner_cptr) { MSE_THROW(nii_vector_range_error("invalid argument - difference_type operator-(const Tnii_vector_ss_const_iterator_type &rhs) const - nii_vector::Tnii_vector_ss_const_iterator_type")); }
auto retval = difference_type((*this).m_index) - difference_type(rhs.m_index);
assert(difference_type((*m_owner_cptr).size()) >= retval);
return retval;
}
const_reference operator*() const {
return (*m_owner_cptr).at(msear_as_a_size_t((*this).m_index));
}
const_reference item() const { return operator*(); }
const_reference previous_item() const {
return (*m_owner_cptr).at(msear_as_a_size_t((*this).m_index - 1));
}
const_pointer operator->() const {
return std::addressof((*m_owner_cptr).at(msear_as_a_size_t((*this).m_index)));
}
const_reference operator[](difference_type _Off) const { return (*m_owner_cptr).at(msear_as_a_size_t(difference_type(m_index) + _Off)); }
bool operator==(const Tnii_vector_ss_const_iterator_type& _Right_cref) const {
if (this->m_owner_cptr != _Right_cref.m_owner_cptr) { MSE_THROW(nii_vector_range_error("invalid argument - Tnii_vector_ss_const_iterator_type& operator==(const Tnii_vector_ss_const_iterator_type& _Right) - Tnii_vector_ss_const_iterator_type - nii_vector")); }
return (_Right_cref.m_index == m_index);
}
bool operator!=(const Tnii_vector_ss_const_iterator_type& _Right_cref) const { return (!(_Right_cref == (*this))); }
bool operator<(const Tnii_vector_ss_const_iterator_type& _Right) const {
if (this->m_owner_cptr != _Right.m_owner_cptr) { MSE_THROW(nii_vector_range_error("invalid argument - Tnii_vector_ss_const_iterator_type& operator<(const Tnii_vector_ss_const_iterator_type& _Right) - Tnii_vector_ss_const_iterator_type - nii_vector")); }
return (m_index < _Right.m_index);
}
bool operator<=(const Tnii_vector_ss_const_iterator_type& _Right) const { return (((*this) < _Right) || (_Right == (*this))); }
bool operator>(const Tnii_vector_ss_const_iterator_type& _Right) const { return (!((*this) <= _Right)); }
bool operator>=(const Tnii_vector_ss_const_iterator_type& _Right) const { return (!((*this) < _Right)); }
void set_to_const_item_pointer(const Tnii_vector_ss_const_iterator_type& _Right_cref) {
(*this) = _Right_cref;
}
template<class _Ty2 = _TVectorConstPointer, class = typename std::enable_if<(std::is_same<_Ty2, _TVectorConstPointer>::value)
&& (mse::HasOrInheritsAssignmentOperator_msemsearray<_Ty2>::value), void>::type>
void assignment_helper1(std::true_type, const Tnii_vector_ss_const_iterator_type& _Right_cref) {
((*this).m_owner_cptr) = _Right_cref.m_owner_cptr;
(*this).m_index = _Right_cref.m_index;
}
void assignment_helper1(std::false_type, const Tnii_vector_ss_const_iterator_type& _Right_cref) {
if (std::addressof(*((*this).m_owner_cptr)) != std::addressof(*(_Right_cref.m_owner_cptr))
|| (!std::is_same<typename std::remove_const<decltype(*((*this).m_owner_cptr))>::type, typename std::remove_const<decltype(*(_Right_cref.m_owner_cptr))>::type>::value)) {
/* In cases where the container pointer type stored by this iterator doesn't support assignment (as with, for
example, mse::TRegisteredFixedPointer<>), this iterator may only be assigned the value of another iterator
pointing to the same container. */
MSE_THROW(nii_vector_range_error("invalid argument - Tnii_vector_ss_const_iterator_type& operator=(const Tnii_vector_ss_const_iterator_type& _Right) - Tnii_vector_ss_const_iterator_type - nii_vector"));
}
(*this).m_index = _Right_cref.m_index;
}
Tnii_vector_ss_const_iterator_type& operator=(const Tnii_vector_ss_const_iterator_type& _Right_cref) {
assignment_helper1(typename mse::HasOrInheritsAssignmentOperator_msemsearray<_TVectorConstPointer>::type(), _Right_cref);
return (*this);
}
template<class _Ty2, class = typename std::enable_if<std::is_convertible<_Ty2, _TVectorConstPointer>::value, void>::type>
Tnii_vector_ss_const_iterator_type& operator=(const Tnii_vector_ss_const_iterator_type<_Ty2, _Ty, _A, _TStateMutex>& _Right_cref) {
return (*this) = Tnii_vector_ss_const_iterator_type(_Right_cref);
}
template<class _Ty2, class = typename std::enable_if<std::is_convertible<_Ty2, _TVectorConstPointer>::value, void>::type>
Tnii_vector_ss_const_iterator_type& operator=(const Tnii_vector_ss_iterator_type<_Ty2, _Ty, _A, _TStateMutex, void>& _Right_cref) {
return (*this) = Tnii_vector_ss_const_iterator_type(_Right_cref);
}
msear_size_t position() const {
return m_index;
}
_TVectorConstPointer target_container_ptr() const {
return m_owner_cptr;
}
/* This iterator is safely "async shareable" if the owner pointer it contains is also "async shareable". */
template<class _Ty2 = _TVectorConstPointer, class = typename std::enable_if<(std::is_same<_Ty2, _TVectorConstPointer>::value)
&& ((std::integral_constant<bool, HasAsyncShareableTagMethod_msemsearray<_Ty2>::Has>())), void>::type>
void async_shareable_tag() const {} /* Indication that this type is eligible to be shared between threads. */
private:
_TVectorConstPointer m_owner_cptr;
msear_size_t m_index = 0;
friend class /*_Myt*/nii_vector<_Ty, _A, _TStateMutex>;
};
/* Tnii_vector_ss_iterator_type is a bounds checked iterator. */
template<typename _TVectorPointer, class _Ty, class _A = std::allocator<_Ty>, class _TStateMutex = default_state_mutex, class = typename std::enable_if<(!std::is_base_of<XScopeTagBase, _TVectorPointer>::value), void>::type>
class Tnii_vector_ss_iterator_type : public random_access_iterator_base<_Ty> {
public:
typedef random_access_iterator_base<_Ty> base_class;
typedef typename base_class::iterator_category iterator_category;
typedef typename base_class::value_type value_type;
typedef typename base_class::difference_type difference_type;
typedef typename base_class::pointer pointer;
typedef typename base_class::reference reference;
typedef const pointer const_pointer;
typedef const reference const_reference;
//template<class = typename std::enable_if<std::is_default_constructible<_TVectorPointer>::value, void>::type>
template<class _TVectorPointer2 = _TVectorPointer, class = typename std::enable_if<(std::is_same<_TVectorPointer2, _TVectorPointer>::value) && (std::is_default_constructible<_TVectorPointer>::value), void>::type>
Tnii_vector_ss_iterator_type() {}
Tnii_vector_ss_iterator_type(const _TVectorPointer& owner_ptr) : m_owner_ptr(owner_ptr) {}
Tnii_vector_ss_iterator_type(_TVectorPointer&& owner_ptr) : m_owner_ptr(std::forward<decltype(owner_ptr)>(owner_ptr)) {}
Tnii_vector_ss_iterator_type(Tnii_vector_ss_iterator_type&& src) = default;
Tnii_vector_ss_iterator_type(const Tnii_vector_ss_iterator_type& src) = default;
template<class _Ty2, class = typename std::enable_if<std::is_convertible<_Ty2, _TVectorPointer>::value, void>::type>
Tnii_vector_ss_iterator_type(const Tnii_vector_ss_iterator_type<_Ty2, _Ty, _A, _TStateMutex>& src) : m_owner_ptr(src.target_container_ptr()), m_index(src.position()) {}
void reset() { set_to_end_marker(); }
bool points_to_an_item() const {
if (m_owner_ptr->size() > m_index) { return true; }
else {
assert(m_index == m_owner_ptr->size());
return false;
}
}
bool points_to_end_marker() const {
if (false == points_to_an_item()) {
assert(m_index == m_owner_ptr->size());
return true;
}
else { return false; }
}
bool points_to_beginning() const {
if (0 == m_index) { return true; }
else { return false; }
}
/* has_next_item_or_end_marker() is just an alias for points_to_an_item(). */
bool has_next_item_or_end_marker() const { return points_to_an_item(); }
/* has_next() is just an alias for points_to_an_item() that's familiar to java programmers. */
bool has_next() const { return has_next_item_or_end_marker(); }
bool has_previous() const {
return ((1 <= m_owner_ptr->size()) && (!points_to_beginning()));
}
void set_to_beginning() {
m_index = 0;
}
void set_to_end_marker() {
m_index = m_owner_ptr->size();
}
void set_to_next() {
if (points_to_an_item()) {
m_index += 1;
assert(m_owner_ptr->size() >= m_index);
}
else {
MSE_THROW(nii_vector_range_error("attempt to use invalid item_pointer - void set_to_next() - Tnii_vector_ss_const_iterator_type - nii_vector"));
}
}
void set_to_previous() {
if (has_previous()) {
m_index -= 1;
}
else {
MSE_THROW(nii_vector_range_error("attempt to use invalid item_pointer - void set_to_previous() - Tnii_vector_ss_iterator_type - nii_vector"));
}
}
Tnii_vector_ss_iterator_type& operator ++() { (*this).set_to_next(); return (*this); }
Tnii_vector_ss_iterator_type operator++(int) { Tnii_vector_ss_iterator_type _Tmp = *this; (*this).set_to_next(); return (_Tmp); }
Tnii_vector_ss_iterator_type& operator --() { (*this).set_to_previous(); return (*this); }
Tnii_vector_ss_iterator_type operator--(int) { Tnii_vector_ss_iterator_type _Tmp = *this; (*this).set_to_previous(); return (_Tmp); }
void advance(difference_type n) {
auto new_index = msear_int(m_index) + n;
if ((0 > new_index) || (m_owner_ptr->size() < msear_size_t(new_index))) {
MSE_THROW(nii_vector_range_error("index out of range - void advance(difference_type n) - Tnii_vector_ss_iterator_type - nii_vector"));
}
else {
m_index = msear_size_t(new_index);
}
}
void regress(difference_type n) { advance(-n); }
Tnii_vector_ss_iterator_type& operator +=(difference_type n) { (*this).advance(n); return (*this); }
Tnii_vector_ss_iterator_type& operator -=(difference_type n) { (*this).regress(n); return (*this); }
Tnii_vector_ss_iterator_type operator+(difference_type n) const {
Tnii_vector_ss_iterator_type retval(*this);
retval.advance(n);
return retval;
}
Tnii_vector_ss_iterator_type operator-(difference_type n) const { return ((*this) + (-n)); }
difference_type operator-(const Tnii_vector_ss_iterator_type& rhs) const {
if (rhs.m_owner_ptr != (*this).m_owner_ptr) { MSE_THROW(nii_vector_range_error("invalid argument - difference_type operator-(const Tnii_vector_ss_iterator_type& rhs) const - nii_vector::Tnii_vector_ss_iterator_type")); }
auto retval = difference_type((*this).m_index) - difference_type(rhs.m_index);
assert(difference_type((*m_owner_ptr).size()) >= retval);
return retval;
}
reference operator*() const {
return (*m_owner_ptr).at(msear_as_a_size_t((*this).m_index));
}
reference item() const { return operator*(); }
reference previous_item() const {
if ((*this).has_previous()) {
return (*m_owner_ptr)[m_index - 1];
}
else {
MSE_THROW(nii_vector_range_error("attempt to use invalid item_pointer - reference previous_item() - Tnii_vector_ss_const_iterator_type - nii_vector"));
}
}
pointer operator->() const {
return std::addressof((*m_owner_ptr).at(msear_as_a_size_t((*this).m_index)));
}
reference operator[](difference_type _Off) const { return (*m_owner_ptr).at(msear_as_a_size_t(difference_type(m_index) + _Off)); }
bool operator==(const Tnii_vector_ss_iterator_type& _Right_cref) const {
if (this->m_owner_ptr != _Right_cref.m_owner_ptr) { MSE_THROW(nii_vector_range_error("invalid argument - Tnii_vector_ss_iterator_type& operator==(const Tnii_vector_ss_iterator_type& _Right) - Tnii_vector_ss_iterator_type - nii_vector")); }
return (_Right_cref.m_index == m_index);
}
bool operator!=(const Tnii_vector_ss_iterator_type& _Right_cref) const { return (!(_Right_cref == (*this))); }
bool operator<(const Tnii_vector_ss_iterator_type& _Right) const {
if (this->m_owner_ptr != _Right.m_owner_ptr) { MSE_THROW(nii_vector_range_error("invalid argument - Tnii_vector_ss_iterator_type& operator<(const Tnii_vector_ss_iterator_type& _Right) - Tnii_vector_ss_iterator_type - nii_vector")); }
return (m_index < _Right.m_index);
}
bool operator<=(const Tnii_vector_ss_iterator_type& _Right) const { return (((*this) < _Right) || (_Right == (*this))); }
bool operator>(const Tnii_vector_ss_iterator_type& _Right) const { return (!((*this) <= _Right)); }
bool operator>=(const Tnii_vector_ss_iterator_type& _Right) const { return (!((*this) < _Right)); }
void set_to_item_pointer(const Tnii_vector_ss_iterator_type& _Right_cref) {
(*this) = _Right_cref;
}
template<class _Ty2 = _TVectorPointer, class = typename std::enable_if<(std::is_same<_Ty2, _TVectorPointer>::value)
&& (mse::HasOrInheritsAssignmentOperator_msemsearray<_Ty2>::value), void>::type>
void assignment_helper1(std::true_type, const Tnii_vector_ss_iterator_type& _Right_cref) {
((*this).m_owner_ptr) = _Right_cref.m_owner_ptr;
(*this).m_index = _Right_cref.m_index;
}
void assignment_helper1(std::false_type, const Tnii_vector_ss_iterator_type& _Right_cref) {
if (std::addressof(*((*this).m_owner_ptr)) != std::addressof(*(_Right_cref.m_owner_ptr))
|| (!std::is_same<typename std::remove_const<decltype(*((*this).m_owner_ptr))>::type, typename std::remove_const<decltype(*(_Right_cref.m_owner_ptr))>::type>::value)) {
/* In cases where the container pointer type stored by this iterator doesn't support assignment (as with, for
example, mse::TRegisteredFixedPointer<>), this iterator may only be assigned the value of another iterator
pointing to the same container. */
MSE_THROW(nii_vector_range_error("invalid argument - Tnii_vector_ss_iterator_type& operator=(const Tnii_vector_ss_iterator_type& _Right) - Tnii_vector_ss_iterator_type - nii_vector"));
}
(*this).m_index = _Right_cref.m_index;
}
Tnii_vector_ss_iterator_type& operator=(const Tnii_vector_ss_iterator_type& _Right_cref) {
assignment_helper1(typename mse::HasOrInheritsAssignmentOperator_msemsearray<_TVectorPointer>::type(), _Right_cref);
return (*this);
}
template<class _Ty2, class = typename std::enable_if<std::is_convertible<_Ty2, _TVectorPointer>::value, void>::type>
Tnii_vector_ss_iterator_type& operator=(const Tnii_vector_ss_iterator_type<_Ty2, _Ty, _A, _TStateMutex>& _Right_cref) {
return (*this) = Tnii_vector_ss_iterator_type(_Right_cref);
}
msear_size_t position() const {
return m_index;
}
_TVectorPointer target_container_ptr() const {
return m_owner_ptr;
}
/*
operator Tnii_vector_ss_const_iterator_type<_TVectorPointer>() const {
Tnii_vector_ss_const_iterator_type<_TVectorPointer> retval;
if (nullptr != m_owner_ptr) {
retval = m_owner_ptr->ss_cbegin<_TVectorPointer>(m_owner_ptr);
retval.advance(msear_int(m_index));
}
return retval;
}
*/
/* This iterator is safely "async shareable" if the owner pointer it contains is also "async shareable". */
template<class _Ty2 = _TVectorPointer, class = typename std::enable_if<(std::is_same<_Ty2, _TVectorPointer>::value)
&& ((std::integral_constant<bool, HasAsyncShareableTagMethod_msemsearray<_Ty2>::Has>())), void>::type>
void async_shareable_tag() const {} /* Indication that this type is eligible to be shared between threads. */
private:
//msear_pointer<_Myt> m_owner_ptr = nullptr;
_TVectorPointer m_owner_ptr;
msear_size_t m_index = 0;
friend class /*_Myt*/nii_vector<_Ty, _A, _TStateMutex>;
template<typename _TVectorConstPointer, class _Ty2, class _A2, class _TStateMutex2, class/* = typename std::enable_if<(!std::is_base_of<XScopeTagBase, _TVectorConstPointer>::value), void>::type*/>
friend class Tnii_vector_ss_const_iterator_type;
};
template<typename _TVectorPointer, class _Ty, class _A = std::allocator<_Ty>, class _TStateMutex = default_state_mutex/*, class = typename std::enable_if<(!std::is_base_of<XScopeTagBase, _TVectorPointer>::value), void>::type*/>
using Tnii_vector_ss_reverse_iterator_type = std::reverse_iterator<Tnii_vector_ss_iterator_type<_TVectorPointer, _Ty, _A, _TStateMutex> >;
template<typename _TVectorConstPointer, class _Ty, class _A = std::allocator<_Ty>, class _TStateMutex = default_state_mutex/*, class = typename std::enable_if<(!std::is_base_of<XScopeTagBase, _TVectorConstPointer>::value), void>::type*/>
using Tnii_vector_ss_const_reverse_iterator_type = std::reverse_iterator<Tnii_vector_ss_const_iterator_type<_TVectorConstPointer, _Ty, _A, _TStateMutex> >;
template<class _Ty, class _A = std::allocator<_Ty>, class _TStateMutex = default_state_mutex>
using Tnii_vector_rp_ss_iterator_type = Tnii_vector_ss_iterator_type<msear_pointer<nii_vector<_Ty, _A, _TStateMutex> >, _Ty, _A, _TStateMutex>;
template<class _Ty, class _A = std::allocator<_Ty>, class _TStateMutex = default_state_mutex>
using Tnii_vector_rp_ss_const_iterator_type = Tnii_vector_ss_const_iterator_type<msear_pointer<const nii_vector<_Ty, _A, _TStateMutex> >, _Ty, _A, _TStateMutex>;
template<class _Ty, class _A = std::allocator<_Ty>, class _TStateMutex = default_state_mutex>
using Tnii_vector_rp_ss_reverse_iterator_type = Tnii_vector_ss_iterator_type<msear_pointer<nii_vector<_Ty, _A, _TStateMutex> >, _Ty, _A, _TStateMutex>;
template<class _Ty, class _A = std::allocator<_Ty>, class _TStateMutex = default_state_mutex>
using Tnii_vector_rp_ss_const_reverse_iterator_type = Tnii_vector_ss_const_reverse_iterator_type<msear_pointer<const nii_vector<_Ty, _A, _TStateMutex> >, _Ty, _A, _TStateMutex>;
template<class _Ty, class _A, class _TStateMutex>
class Tnii_vector_xscope_ss_iterator_type;
template<class _Ty, class _A = std::allocator<_Ty>, class _TStateMutex = default_state_mutex>
class Tnii_vector_xscope_ss_const_iterator_type : public Tnii_vector_rp_ss_const_iterator_type<_Ty, _A, _TStateMutex>, public XScopeContainsNonOwningScopeReferenceTagBase, public StrongPointerNotAsyncShareableTagBase {
public:
typedef Tnii_vector_rp_ss_const_iterator_type<_Ty, _A, _TStateMutex> base_class;
typedef typename base_class::iterator_category iterator_category;
typedef typename base_class::value_type value_type;
typedef typename base_class::difference_type difference_type;
typedef typename base_class::pointer pointer;
typedef typename base_class::reference reference;
typedef const pointer const_pointer;
typedef const reference const_reference;
template <typename _TXScopePointer, class = typename std::enable_if<
std::is_convertible<_TXScopePointer, mse::TXScopeItemFixedConstPointer<const nii_vector<_Ty, _A, _TStateMutex> > >::value
|| std::is_convertible<_TXScopePointer, mse::TXScopeItemFixedPointer<nii_vector<_Ty, _A, _TStateMutex> > >::value
|| std::is_convertible<_TXScopePointer, mse::TXScopeFixedConstPointer<const nii_vector<_Ty, _A, _TStateMutex> > >::value
|| std::is_convertible<_TXScopePointer, mse::TXScopeFixedPointer<nii_vector<_Ty, _A, _TStateMutex> > >::value
, void>::type>
Tnii_vector_xscope_ss_const_iterator_type(const _TXScopePointer& owner_ptr) : Tnii_vector_rp_ss_const_iterator_type<_Ty, _A, _TStateMutex>((*owner_ptr).ss_cbegin()) {}
Tnii_vector_xscope_ss_const_iterator_type(const Tnii_vector_xscope_ss_const_iterator_type& src_cref) : Tnii_vector_rp_ss_const_iterator_type<_Ty, _A, _TStateMutex>(src_cref) {}
Tnii_vector_xscope_ss_const_iterator_type(const Tnii_vector_xscope_ss_iterator_type<_Ty, _A, _TStateMutex>& src_cref) : Tnii_vector_rp_ss_const_iterator_type<_Ty, _A, _TStateMutex>(src_cref) {}
~Tnii_vector_xscope_ss_const_iterator_type() {}
const Tnii_vector_rp_ss_const_iterator_type<_Ty, _A, _TStateMutex>& nii_vector_ss_const_iterator_type() const {
return (*this);
}
Tnii_vector_rp_ss_const_iterator_type<_Ty, _A, _TStateMutex>& nii_vector_ss_const_iterator_type() {
return (*this);
}
const Tnii_vector_rp_ss_const_iterator_type<_Ty, _A, _TStateMutex>& mvssci() const { return nii_vector_ss_const_iterator_type(); }
Tnii_vector_rp_ss_const_iterator_type<_Ty, _A, _TStateMutex>& mvssci() { return nii_vector_ss_const_iterator_type(); }
void reset() { Tnii_vector_rp_ss_const_iterator_type<_Ty, _A, _TStateMutex>::reset(); }
bool points_to_an_item() const { return Tnii_vector_rp_ss_const_iterator_type<_Ty, _A, _TStateMutex>::points_to_an_item(); }
bool points_to_end_marker() const { return Tnii_vector_rp_ss_const_iterator_type<_Ty, _A, _TStateMutex>::points_to_end_marker(); }
bool points_to_beginning() const { return Tnii_vector_rp_ss_const_iterator_type<_Ty, _A, _TStateMutex>::points_to_beginning(); }
/* has_next_item_or_end_marker() is just an alias for points_to_an_item(). */
bool has_next_item_or_end_marker() const { return Tnii_vector_rp_ss_const_iterator_type<_Ty, _A, _TStateMutex>::has_next_item_or_end_marker(); }
/* has_next() is just an alias for points_to_an_item() that's familiar to java programmers. */
bool has_next() const { return Tnii_vector_rp_ss_const_iterator_type<_Ty, _A, _TStateMutex>::has_next(); }
bool has_previous() const { return Tnii_vector_rp_ss_const_iterator_type<_Ty, _A, _TStateMutex>::has_previous(); }
void set_to_beginning() { Tnii_vector_rp_ss_const_iterator_type<_Ty, _A, _TStateMutex>::set_to_beginning(); }
void set_to_end_marker() { Tnii_vector_rp_ss_const_iterator_type<_Ty, _A, _TStateMutex>::set_to_end_marker(); }
void set_to_next() { Tnii_vector_rp_ss_const_iterator_type<_Ty, _A, _TStateMutex>::set_to_next(); }
void set_to_previous() { Tnii_vector_rp_ss_const_iterator_type<_Ty, _A, _TStateMutex>::set_to_previous(); }
Tnii_vector_xscope_ss_const_iterator_type& operator ++() { Tnii_vector_rp_ss_const_iterator_type<_Ty, _A, _TStateMutex>::operator ++(); return (*this); }
Tnii_vector_xscope_ss_const_iterator_type operator++(int) { Tnii_vector_xscope_ss_const_iterator_type _Tmp = *this; Tnii_vector_rp_ss_const_iterator_type<_Ty, _A, _TStateMutex>::operator++(); return (_Tmp); }
Tnii_vector_xscope_ss_const_iterator_type& operator --() { Tnii_vector_rp_ss_const_iterator_type<_Ty, _A, _TStateMutex>::operator --(); return (*this); }
Tnii_vector_xscope_ss_const_iterator_type operator--(int) { Tnii_vector_xscope_ss_const_iterator_type _Tmp = *this; Tnii_vector_rp_ss_const_iterator_type<_Ty, _A, _TStateMutex>::operator--(); return (_Tmp); }
void advance(difference_type n) { Tnii_vector_rp_ss_const_iterator_type<_Ty, _A, _TStateMutex>::advance(n); }
void regress(difference_type n) { Tnii_vector_rp_ss_const_iterator_type<_Ty, _A, _TStateMutex>::regress(n); }
Tnii_vector_xscope_ss_const_iterator_type& operator +=(difference_type n) { Tnii_vector_rp_ss_const_iterator_type<_Ty, _A, _TStateMutex>::operator +=(n); return (*this); }
Tnii_vector_xscope_ss_const_iterator_type& operator -=(difference_type n) { Tnii_vector_rp_ss_const_iterator_type<_Ty, _A, _TStateMutex>::operator -=(n); return (*this); }
Tnii_vector_xscope_ss_const_iterator_type operator+(difference_type n) const { auto retval = (*this); retval += n; return retval; }
Tnii_vector_xscope_ss_const_iterator_type operator-(difference_type n) const { return ((*this) + (-n)); }
difference_type operator-(const Tnii_vector_xscope_ss_const_iterator_type& _Right_cref) const { return Tnii_vector_rp_ss_const_iterator_type<_Ty, _A, _TStateMutex>::operator-(_Right_cref); }
const_reference operator*() const { return Tnii_vector_rp_ss_const_iterator_type<_Ty, _A, _TStateMutex>::operator*(); }
const_reference item() const { return operator*(); }
const_reference previous_item() const { return Tnii_vector_rp_ss_const_iterator_type<_Ty, _A, _TStateMutex>::previous_item(); }
const_pointer operator->() const { return Tnii_vector_rp_ss_const_iterator_type<_Ty, _A, _TStateMutex>::operator->(); }
const_reference operator[](difference_type _Off) const { return Tnii_vector_rp_ss_const_iterator_type<_Ty, _A, _TStateMutex>::operator[](_Off); }
Tnii_vector_xscope_ss_const_iterator_type& operator=(const Tnii_vector_rp_ss_const_iterator_type<_Ty, _A, _TStateMutex>& _Right_cref) {
if ((&(*_Right_cref.target_container_ptr())) != (&(*(*this).target_container_ptr()))) { MSE_THROW(nii_vector_range_error("invalid argument - Tnii_vector_xscope_ss_const_iterator_type& operator=(const Tnii_vector_xscope_ss_const_iterator_type& _Right_cref) - nii_vector::Tnii_vector_xscope_ss_const_iterator_type")); }
Tnii_vector_rp_ss_const_iterator_type<_Ty, _A, _TStateMutex>::operator=(_Right_cref);
return (*this);
}
Tnii_vector_xscope_ss_const_iterator_type& operator=(const Tnii_vector_rp_ss_iterator_type<_Ty, _A, _TStateMutex>& _Right_cref) {
if ((&(*_Right_cref.target_container_ptr())) != (&(*(*this).target_container_ptr()))) { MSE_THROW(nii_vector_range_error("invalid argument - Tnii_vector_xscope_ss_const_iterator_type& operator=(const Tnii_vector_rp_ss_iterator_type<_Ty, _A, _TStateMutex>& _Right_cref) - nii_vector::Tnii_vector_xscope_ss_const_iterator_type")); }
return operator=(Tnii_vector_rp_ss_const_iterator_type<_Ty, _A, _TStateMutex>(_Right_cref));
}
bool operator==(const Tnii_vector_xscope_ss_const_iterator_type& _Right_cref) const { return Tnii_vector_rp_ss_const_iterator_type<_Ty, _A, _TStateMutex>::operator==(_Right_cref); }
bool operator!=(const Tnii_vector_xscope_ss_const_iterator_type& _Right_cref) const { return (!(_Right_cref == (*this))); }
bool operator<(const Tnii_vector_xscope_ss_const_iterator_type& _Right) const { return Tnii_vector_rp_ss_const_iterator_type<_Ty, _A, _TStateMutex>::operator<(_Right); }
bool operator<=(const Tnii_vector_xscope_ss_const_iterator_type& _Right) const { return Tnii_vector_rp_ss_const_iterator_type<_Ty, _A, _TStateMutex>::operator<=(_Right); }
bool operator>(const Tnii_vector_xscope_ss_const_iterator_type& _Right) const { return Tnii_vector_rp_ss_const_iterator_type<_Ty, _A, _TStateMutex>::operator>(_Right); }
bool operator>=(const Tnii_vector_xscope_ss_const_iterator_type& _Right) const { return Tnii_vector_rp_ss_const_iterator_type<_Ty, _A, _TStateMutex>::operator>=(_Right); }
void set_to_const_item_pointer(const Tnii_vector_xscope_ss_const_iterator_type& _Right_cref) { Tnii_vector_rp_ss_const_iterator_type<_Ty, _A, _TStateMutex>::set_to_item_pointer(_Right_cref); }
msear_size_t position() const { return Tnii_vector_rp_ss_const_iterator_type<_Ty, _A, _TStateMutex>::position(); }
auto target_container_ptr() const {
return mse::us::unsafe_make_xscope_const_pointer_to(*(Tnii_vector_rp_ss_const_iterator_type<_Ty, _A, _TStateMutex>::target_container_ptr()));
}
void xscope_ss_iterator_type_tag() const {}
void not_async_shareable_tag() const {} /* Indication that this type is not eligible to be shared between threads. */
private:
void* operator new(size_t size) { return ::operator new(size); }
//typename Tnii_vector_rp_ss_const_iterator_type<_Ty, _A, _TStateMutex> (*this);
friend class /*_Myt*/nii_vector<_Ty, _A, _TStateMutex>;
template<class _Ty2, class _A2, class _TStateMutex2>
friend class Tnii_vector_xscope_ss_iterator_type;
};
template<class _Ty, class _A = std::allocator<_Ty>, class _TStateMutex = default_state_mutex>
class Tnii_vector_xscope_ss_iterator_type : public Tnii_vector_rp_ss_iterator_type<_Ty, _A, _TStateMutex>, public XScopeContainsNonOwningScopeReferenceTagBase, public StrongPointerNotAsyncShareableTagBase {
public:
typedef Tnii_vector_rp_ss_iterator_type<_Ty, _A, _TStateMutex> base_class;
typedef typename base_class::iterator_category iterator_category;
typedef typename base_class::value_type value_type;
typedef typename base_class::difference_type difference_type;
typedef typename base_class::pointer pointer;
typedef typename base_class::reference reference;
typedef const pointer const_pointer;
typedef const reference const_reference;
template <typename _TXScopePointer, class = typename std::enable_if<
std::is_convertible<_TXScopePointer, mse::TXScopeItemFixedPointer<nii_vector<_Ty, _A, _TStateMutex> > >::value
|| std::is_convertible<_TXScopePointer, mse::TXScopeFixedPointer<nii_vector<_Ty, _A, _TStateMutex> > >::value
, void>::type>
Tnii_vector_xscope_ss_iterator_type(const _TXScopePointer& owner_ptr) : Tnii_vector_rp_ss_iterator_type<_Ty, _A, _TStateMutex>((*owner_ptr).ss_begin()) {}
Tnii_vector_xscope_ss_iterator_type(const Tnii_vector_xscope_ss_iterator_type& src_cref) : Tnii_vector_rp_ss_iterator_type<_Ty, _A, _TStateMutex>(src_cref) {}
~Tnii_vector_xscope_ss_iterator_type() {}
const Tnii_vector_rp_ss_iterator_type<_Ty, _A, _TStateMutex>& nii_vector_ss_iterator_type() const {
return (*this);
}
Tnii_vector_rp_ss_iterator_type<_Ty, _A, _TStateMutex>& nii_vector_ss_iterator_type() {
return (*this);
}
const Tnii_vector_rp_ss_iterator_type<_Ty, _A, _TStateMutex>& mvssi() const { return nii_vector_ss_iterator_type(); }
Tnii_vector_rp_ss_iterator_type<_Ty, _A, _TStateMutex>& mvssi() { return nii_vector_ss_iterator_type(); }
void reset() { Tnii_vector_rp_ss_iterator_type<_Ty, _A, _TStateMutex>::reset(); }
bool points_to_an_item() const { return Tnii_vector_rp_ss_iterator_type<_Ty, _A, _TStateMutex>::points_to_an_item(); }
bool points_to_end_marker() const { return Tnii_vector_rp_ss_iterator_type<_Ty, _A, _TStateMutex>::points_to_end_marker(); }
bool points_to_beginning() const { return Tnii_vector_rp_ss_iterator_type<_Ty, _A, _TStateMutex>::points_to_beginning(); }
/* has_next_item_or_end_marker() is just an alias for points_to_an_item(). */
bool has_next_item_or_end_marker() const { return Tnii_vector_rp_ss_iterator_type<_Ty, _A, _TStateMutex>::has_next_item_or_end_marker(); }
/* has_next() is just an alias for points_to_an_item() that's familiar to java programmers. */
bool has_next() const { return Tnii_vector_rp_ss_iterator_type<_Ty, _A, _TStateMutex>::has_next(); }
bool has_previous() const { return Tnii_vector_rp_ss_iterator_type<_Ty, _A, _TStateMutex>::has_previous(); }
void set_to_beginning() { Tnii_vector_rp_ss_iterator_type<_Ty, _A, _TStateMutex>::set_to_beginning(); }
void set_to_end_marker() { Tnii_vector_rp_ss_iterator_type<_Ty, _A, _TStateMutex>::set_to_end_marker(); }
void set_to_next() { Tnii_vector_rp_ss_iterator_type<_Ty, _A, _TStateMutex>::set_to_next(); }
void set_to_previous() { Tnii_vector_rp_ss_iterator_type<_Ty, _A, _TStateMutex>::set_to_previous(); }
Tnii_vector_xscope_ss_iterator_type& operator ++() { Tnii_vector_rp_ss_iterator_type<_Ty, _A, _TStateMutex>::operator ++(); return (*this); }
Tnii_vector_xscope_ss_iterator_type operator++(int) { Tnii_vector_xscope_ss_iterator_type _Tmp = *this; Tnii_vector_rp_ss_iterator_type<_Ty, _A, _TStateMutex>::operator++(); return (_Tmp); }
Tnii_vector_xscope_ss_iterator_type& operator --() { Tnii_vector_rp_ss_iterator_type<_Ty, _A, _TStateMutex>::operator --(); return (*this); }
Tnii_vector_xscope_ss_iterator_type operator--(int) { Tnii_vector_xscope_ss_iterator_type _Tmp = *this; Tnii_vector_rp_ss_iterator_type<_Ty, _A, _TStateMutex>::operator--(); return (_Tmp); }
void advance(difference_type n) { Tnii_vector_rp_ss_iterator_type<_Ty, _A, _TStateMutex>::advance(n); }
void regress(difference_type n) { Tnii_vector_rp_ss_iterator_type<_Ty, _A, _TStateMutex>::regress(n); }
Tnii_vector_xscope_ss_iterator_type& operator +=(difference_type n) { Tnii_vector_rp_ss_iterator_type<_Ty, _A, _TStateMutex>::operator +=(n); return (*this); }
Tnii_vector_xscope_ss_iterator_type& operator -=(difference_type n) { Tnii_vector_rp_ss_iterator_type<_Ty, _A, _TStateMutex>::operator -=(n); return (*this); }
Tnii_vector_xscope_ss_iterator_type operator+(difference_type n) const { auto retval = (*this); retval += n; return retval; }
Tnii_vector_xscope_ss_iterator_type operator-(difference_type n) const { return ((*this) + (-n)); }
difference_type operator-(const Tnii_vector_xscope_ss_iterator_type& _Right_cref) const { return Tnii_vector_rp_ss_iterator_type<_Ty, _A, _TStateMutex>::operator-(_Right_cref); }
reference operator*() const { return Tnii_vector_rp_ss_iterator_type<_Ty, _A, _TStateMutex>::operator*(); }
reference item() const { return operator*(); }
reference previous_item() const { return Tnii_vector_rp_ss_iterator_type<_Ty, _A, _TStateMutex>::previous_item(); }
pointer operator->() const { return Tnii_vector_rp_ss_iterator_type<_Ty, _A, _TStateMutex>::operator->(); }
reference operator[](difference_type _Off) const { return Tnii_vector_rp_ss_iterator_type<_Ty, _A, _TStateMutex>::operator[](_Off); }
Tnii_vector_xscope_ss_iterator_type& operator=(const Tnii_vector_rp_ss_iterator_type<_Ty, _A, _TStateMutex>& _Right_cref) {
if ((&(*_Right_cref.target_container_ptr())) != (&(*(*this).target_container_ptr()))) { MSE_THROW(nii_vector_range_error("invalid argument - Tnii_vector_xscope_ss_iterator_type& operator=(const Tnii_vector_xscope_ss_iterator_type& _Right_cref) - nii_vector::Tnii_vector_xscope_ss_iterator_type")); }
Tnii_vector_rp_ss_iterator_type<_Ty, _A, _TStateMutex>::operator=(_Right_cref);
return (*this);
}
bool operator==(const Tnii_vector_xscope_ss_iterator_type& _Right_cref) const { return Tnii_vector_rp_ss_iterator_type<_Ty, _A, _TStateMutex>::operator==(_Right_cref); }
bool operator!=(const Tnii_vector_xscope_ss_iterator_type& _Right_cref) const { return (!(_Right_cref == (*this))); }
bool operator<(const Tnii_vector_xscope_ss_iterator_type& _Right) const { return Tnii_vector_rp_ss_iterator_type<_Ty, _A, _TStateMutex>::operator<(_Right); }
bool operator<=(const Tnii_vector_xscope_ss_iterator_type& _Right) const { return Tnii_vector_rp_ss_iterator_type<_Ty, _A, _TStateMutex>::operator<=(_Right); }
bool operator>(const Tnii_vector_xscope_ss_iterator_type& _Right) const { return Tnii_vector_rp_ss_iterator_type<_Ty, _A, _TStateMutex>::operator>(_Right); }
bool operator>=(const Tnii_vector_xscope_ss_iterator_type& _Right) const { return Tnii_vector_rp_ss_iterator_type<_Ty, _A, _TStateMutex>::operator>=(_Right); }
void set_to_item_pointer(const Tnii_vector_xscope_ss_iterator_type& _Right_cref) { Tnii_vector_rp_ss_iterator_type<_Ty, _A, _TStateMutex>::set_to_item_pointer(_Right_cref); }
msear_size_t position() const { return Tnii_vector_rp_ss_iterator_type<_Ty, _A, _TStateMutex>::position(); }
auto target_container_ptr() const {
return mse::us::unsafe_make_xscope_pointer_to(*(Tnii_vector_rp_ss_iterator_type<_Ty, _A, _TStateMutex>::target_container_ptr()));
}
void xscope_ss_iterator_type_tag() const {}
void not_async_shareable_tag() const {} /* Indication that this type is not eligible to be shared between threads. */
private:
void* operator new(size_t size) { return ::operator new(size); }
//typename Tnii_vector_rp_ss_iterator_type<_Ty, _A, _TStateMutex> (*this);
friend class /*_Myt*/nii_vector<_Ty, _A, _TStateMutex>;
};
/* nii_vector<> is essentially a memory-safe vector that does not expose (unprotected) non-static member functions
like begin() or end() which return (memory) unsafe iterators. It does provide static member function templates
like ss_begin<>(...) and ss_end<>(...) which take a pointer parameter and return a (bounds-checked) iterator that
inherits the safety of the given pointer. nii_vector<> also supports "scope" iterators which are safe without any
run-time overhead. nii_vector<> is a data type that is eligible to be shared between asynchronous threads. */
template<class _Ty, class _A = std::allocator<_Ty>, class _TStateMutex = default_state_mutex>
class nii_vector {
public:
typedef std::vector<_Ty, _A> std_vector;
typedef std_vector _MV;
typedef nii_vector _Myt;
typedef std_vector base_class;
typedef typename std_vector::allocator_type allocator_type;
typedef typename std_vector::value_type value_type;
//typedef typename std_vector::size_type size_type;
typedef msev_size_t size_type;
//typedef typename std_vector::difference_type difference_type;
typedef msev_int difference_type;
typedef typename std_vector::pointer pointer;
typedef typename std_vector::const_pointer const_pointer;
typedef typename std_vector::reference reference;
typedef typename std_vector::const_reference const_reference;
typedef typename std_vector::iterator iterator;
typedef typename std_vector::const_iterator const_iterator;
typedef typename std_vector::reverse_iterator reverse_iterator;
typedef typename std_vector::const_reverse_iterator const_reverse_iterator;
explicit nii_vector(const _A& _Al = _A())
: m_vector(_Al) {
/*m_debug_size = size();*/
}
explicit nii_vector(size_type _N)
: m_vector(msev_as_a_size_t(_N)) {
/*m_debug_size = size();*/
}
explicit nii_vector(size_type _N, const _Ty& _V, const _A& _Al = _A())
: m_vector(msev_as_a_size_t(_N), _V, _Al) {
/*m_debug_size = size();*/
}
nii_vector(std_vector&& _X) : m_vector(std::forward<decltype(_X)>(_X)) { /*m_debug_size = size();*/ }
nii_vector(const std_vector& _X) : m_vector(_X) { /*m_debug_size = size();*/ }
nii_vector(_Myt&& _X) : m_vector(std::forward<decltype(_X.contained_vector())>(_X.contained_vector())) { /*m_debug_size = size();*/ }
nii_vector(const _Myt& _X) : m_vector(_X.contained_vector()) { /*m_debug_size = size();*/ }
typedef typename std_vector::const_iterator _It;
/* Note that safety cannot be guaranteed when using these constructors that take unsafe typename base_class::iterator and/or pointer parameters. */
nii_vector(_It _F, _It _L, const _A& _Al = _A()) : m_vector(_F, _L, _Al) { /*m_debug_size = size();*/ }
nii_vector(const _Ty* _F, const _Ty* _L, const _A& _Al = _A()) : m_vector(_F, _L, _Al) { /*m_debug_size = size();*/ }
template<class _Iter
//, class = typename std::enable_if<_mse_Is_iterator<_Iter>::value, void>::type
, class = _mse_RequireInputIter<_Iter> >
nii_vector(const _Iter& _First, const _Iter& _Last) : m_vector(_First, _Last) { /*m_debug_size = size();*/ }
template<class _Iter
//, class = typename std::enable_if<_mse_Is_iterator<_Iter>::value, void>::type
, class = _mse_RequireInputIter<_Iter> >
//nii_vector(const _Iter& _First, const _Iter& _Last, const typename std_vector::_Alloc& _Al) : m_vector(_First, _Last, _Al) { /*m_debug_size = size();*/ }
nii_vector(const _Iter& _First, const _Iter& _Last, const _A& _Al) : m_vector(_First, _Last, _Al) { /*m_debug_size = size();*/ }
_Myt& operator=(const std_vector& _X) {
std::lock_guard<_TStateMutex> lock1(m_mutex1);
m_vector.operator =(_X);
/*m_debug_size = size();*/
return (*this);
}
_Myt& operator=(_Myt&& _X) {
std::lock_guard<_TStateMutex> lock1(m_mutex1);
m_vector.operator=(std::forward<std_vector>(_X.contained_vector()));
return (*this);
}
_Myt& operator=(const _Myt& _X) {
std::lock_guard<_TStateMutex> lock1(m_mutex1);
m_vector.operator=(_X.contained_vector());
return (*this);
}
~nii_vector() {
mse::destructor_lock_guard1<_TStateMutex> lock1(m_mutex1);
/* This is just a no-op function that will cause a compile error when _Ty is not an eligible type. */
valid_if_Ty_is_not_an_xscope_type();
}
operator _MV() const { return this->contained_vector(); }
void reserve(size_type _Count)
{ // determine new minimum length of allocated storage
std::lock_guard<_TStateMutex> lock1(m_mutex1);
m_vector.reserve(msev_as_a_size_t(_Count));
}
size_type capacity() const _NOEXCEPT
{ // return current length of allocated storage
return m_vector.capacity();
}
void shrink_to_fit() { // reduce capacity
std::lock_guard<_TStateMutex> lock1(m_mutex1);
m_vector.shrink_to_fit();
}
void resize(size_type _N, const _Ty& _X = _Ty()) {
std::lock_guard<_TStateMutex> lock1(m_mutex1);
m_vector.resize(msev_as_a_size_t(_N), _X);
}
typename std_vector::const_reference operator[](msev_size_t _P) const {
return (*this).at(msev_as_a_size_t(_P));
}
typename std_vector::reference operator[](msev_size_t _P) {
return (*this).at(msev_as_a_size_t(_P));
}
typename std_vector::reference front() { // return first element of mutable sequence
if (0 == (*this).size()) { MSE_THROW(nii_vector_range_error("front() on empty - typename std_vector::reference front() - nii_vector")); }
return m_vector.front();
}
typename std_vector::const_reference front() const { // return first element of nonmutable sequence
if (0 == (*this).size()) { MSE_THROW(nii_vector_range_error("front() on empty - typename std_vector::const_reference front() - nii_vector")); }
return m_vector.front();
}
typename std_vector::reference back() { // return last element of mutable sequence
if (0 == (*this).size()) { MSE_THROW(nii_vector_range_error("back() on empty - typename std_vector::reference back() - nii_vector")); }
return m_vector.back();
}
typename std_vector::const_reference back() const { // return last element of nonmutable sequence
if (0 == (*this).size()) { MSE_THROW(nii_vector_range_error("back() on empty - typename std_vector::const_reference back() - nii_vector")); }
return m_vector.back();
}
void push_back(_Ty&& _X) {
std::lock_guard<_TStateMutex> lock1(m_mutex1);
m_vector.push_back(std::forward<decltype(_X)>(_X));
}
void push_back(const _Ty& _X) {
std::lock_guard<_TStateMutex> lock1(m_mutex1);
m_vector.push_back(_X);
}
void pop_back() {
std::lock_guard<_TStateMutex> lock1(m_mutex1);
m_vector.pop_back();
}
void assign(_It _F, _It _L) {
smoke_check_source_iterators(_F, _L);
std::lock_guard<_TStateMutex> lock1(m_mutex1);
m_vector.assign(_F, _L);
/*m_debug_size = size();*/
}
template<class _Iter>
void assign(const _Iter& _First, const _Iter& _Last) { // assign [_First, _Last)
smoke_check_source_iterators(_First, _Last);
std::lock_guard<_TStateMutex> lock1(m_mutex1);
m_vector.assign(_First, _Last);
/*m_debug_size = size();*/
}
void assign(size_type _N, const _Ty& _X = _Ty()) {
std::lock_guard<_TStateMutex> lock1(m_mutex1);
m_vector.assign(msev_as_a_size_t(_N), _X);
/*m_debug_size = size();*/
}
template<class _Iter>
void smoke_check_source_iterators_helper(std::true_type, const _Iter& _First, const _Iter& _Last) {
if (_Last < _First)/*comparison operations should also verify that safe iterators point to the same container*/ {
MSE_THROW(nii_vector_range_error("invalid arguments - void smoke_check_source_iterators() const - nii_vector"));
} else if ((!(*this).empty()) && (_First < _Last)) {
#ifdef MSE_NII_VECTOR_ENABLE_SOURCE_ITER_ALIAS_CHECK
/* check for overlap between source and target sequences */
auto start_of_this_ptr = std::addressof(*begin());
auto end_of_this_ptr = std::addressof(*(end() - 1)) + 1;
auto _First_ptr = std::addressof(*_First);
auto _Last_ptr = std::addressof(*(_Last - 1)) + 1;
if ((end_of_this_ptr > _First_ptr) && (start_of_this_ptr < _Last_ptr)) {
MSE_THROW(nii_vector_range_error("invalid arguments - void smoke_check_source_iterators() const - nii_vector"));
}
#endif // !MSE_NII_VECTOR_ENABLE_SOURCE_ITER_ALIAS_CHECK
}
}
template<class _Iter>
void smoke_check_source_iterators_helper(std::false_type, const _Iter&, const _Iter&) {}
template<class _Iter>
void smoke_check_source_iterators(const _Iter& _First, const _Iter& _Last) {
smoke_check_source_iterators_helper(typename HasOrInheritsLessThanOperator_msemsevector<_Iter>::type(), _First, _Last);
}
template<class ..._Valty>
void emplace_back(_Valty&& ..._Val)
{ // insert by moving into element at end
std::lock_guard<_TStateMutex> lock1(m_mutex1);
m_vector.emplace_back(std::forward<_Valty>(_Val)...);
/*m_debug_size = size();*/
}
void clear() {
std::lock_guard<_TStateMutex> lock1(m_mutex1);
m_vector.clear();
/*m_debug_size = size();*/
}
void swap(_Myt& _Other) { // swap contents with _Other
std::lock_guard<_TStateMutex> lock1(m_mutex1);
m_vector.swap(_Other.m_vector);
}
void swap(_MV& _Other) { // swap contents with _Other
std::lock_guard<_TStateMutex> lock1(m_mutex1);
m_vector.swap(_Other);
}
size_type size() const _NOEXCEPT
{ // return length of sequence
return m_vector.size();
}
size_type max_size() const _NOEXCEPT
{ // return maximum possible length of sequence
return m_vector.max_size();
}
bool empty() const _NOEXCEPT
{ // test if sequence is empty
return m_vector.empty();
}
_A get_allocator() const _NOEXCEPT
{ // return allocator object for values
return m_vector.get_allocator();
}
reference at(msev_size_t _Pos)
{ // subscript mutable sequence with checking
return m_vector.at(msev_as_a_size_t(_Pos));
}
const_reference at(msev_size_t _Pos) const
{ // subscript nonmutable sequence with checking
return m_vector.at(msev_as_a_size_t(_Pos));