1 //
2 // Copyright (c) 2015 Arthur O'Dwyer
3 // Copyright 2017-2018 by Martin Moene
4 //
5 // https://github.com/martinmoene/ring-span-lite
6 //
7 // Distributed under the Boost Software License, Version 1.0.
8 // (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9
10 #pragma once
11
12 #ifndef NONSTD_RING_SPAN_LITE_HPP
13 #define NONSTD_RING_SPAN_LITE_HPP
14
15 #define ring_span_lite_MAJOR 0
16 #define ring_span_lite_MINOR 2
17 #define ring_span_lite_PATCH 0
18
19 #define ring_span_lite_VERSION nsrs_STRINGIFY(ring_span_lite_MAJOR) "." nsrs_STRINGIFY(ring_span_lite_MINOR) "." nsrs_STRINGIFY(ring_span_lite_PATCH)
20
21 #define nsrs_STRINGIFY( x ) nsrs_STRINGIFY_( x )
22 #define nsrs_STRINGIFY_( x ) #x
23
24 // ring-span-lite configuration:
25
26 #define nsrs_RING_SPAN_DEFAULT 0
27 #define nsrs_RING_SPAN_NONSTD 1
28 #define nsrs_RING_SPAN_STD 2
29
30 #if !defined( nsrs_CONFIG_SELECT_RING_SPAN )
31 # define nsrs_CONFIG_SELECT_RING_SPAN ( nsrs_HAVE_STD_RING_SPAN ? nsrs_RING_SPAN_STD : nsrs_RING_SPAN_NONSTD )
32 #endif
33
34 #ifndef nsrs_CONFIG_STRICT_P0059
35 # define nsrs_CONFIG_STRICT_P0059 0
36 #endif
37
38 #define nsrs_RING_SPAN_LITE_EXTENSION (! nsrs_CONFIG_STRICT_P0059)
39
40 #ifndef nsrs_CONFIG_CONFIRMS_COMPILATION_ERRORS
41 # define nsrs_CONFIG_CONFIRMS_COMPILATION_ERRORS 0
42 #endif
43
44 // C++ language version detection (C++20 is speculative):
45 // Note: VC14.0/1900 (VS2015) lacks too much from C++14.
46
47 #ifndef nsrs_CPLUSPLUS
48 # if defined(_MSVC_LANG ) && !defined(__clang__)
49 # define nsrs_CPLUSPLUS (_MSC_VER == 1900 ? 201103L : _MSVC_LANG )
50 # else
51 # define nsrs_CPLUSPLUS __cplusplus
52 # endif
53 #endif
54
55 #define nsrs_CPP98_OR_GREATER ( nsrs_CPLUSPLUS >= 199711L )
56 #define nsrs_CPP11_OR_GREATER ( nsrs_CPLUSPLUS >= 201103L )
57 #define nsrs_CPP11_OR_GREATER_ ( nsrs_CPLUSPLUS >= 201103L )
58 #define nsrs_CPP14_OR_GREATER ( nsrs_CPLUSPLUS >= 201402L )
59 #define nsrs_CPP17_OR_GREATER ( nsrs_CPLUSPLUS >= 201703L )
60 #define nsrs_CPP20_OR_GREATER ( nsrs_CPLUSPLUS >= 202000L )
61
62 // Use C++XX std::ring_span if available and requested:
63
64 #define nsrs_HAVE_STD_RING_SPAN 0
65
66 //#if nsrs_CPP17_OR_GREATER && defined(__has_include )
67 //# if __has_include( <any> )
68 //# define nsrs_HAVE_STD_RING_SPAN 1
69 //# else
70 //# define nsrs_HAVE_STD_RING_SPAN 0
71 //# endif
72 //#else
73 //# define nsrs_HAVE_STD_RING_SPAN 0
74 //#endif
75
76 #define nsrs_USES_STD_RING_SPAN ( (nsrs_CONFIG_SELECT_RING_SPAN == nsrs_RING_SPAN_STD) || ((nsrs_CONFIG_SELECT_RING_SPAN == nsrs_RING_SPAN_DEFAULT) && nsrs_HAVE_STD_RING_SPAN) )
77
78 // Compiler versions:
79 //
80 // MSVC++ 6.0 _MSC_VER == 1200 (Visual Studio 6.0)
81 // MSVC++ 7.0 _MSC_VER == 1300 (Visual Studio .NET 2002)
82 // MSVC++ 7.1 _MSC_VER == 1310 (Visual Studio .NET 2003)
83 // MSVC++ 8.0 _MSC_VER == 1400 (Visual Studio 2005)
84 // MSVC++ 9.0 _MSC_VER == 1500 (Visual Studio 2008)
85 // MSVC++ 10.0 _MSC_VER == 1600 (Visual Studio 2010)
86 // MSVC++ 11.0 _MSC_VER == 1700 (Visual Studio 2012)
87 // MSVC++ 12.0 _MSC_VER == 1800 (Visual Studio 2013)
88 // MSVC++ 14.0 _MSC_VER == 1900 (Visual Studio 2015)
89 // ............_MSVC_LANG: 201402 for -std:c++14, default
90 // MSVC++ 14.1 _MSC_VER >= 1910 (Visual Studio 2017)
91 // ............_MSVC_LANG: 201402 for -std:c++14, default
92 // ............_MSVC_LANG: 201703 for -std:c++17
93
94 #if defined(_MSC_VER ) && !defined(__clang__)
95 # define nsrs_COMPILER_MSVC_VER (_MSC_VER )
96 # define nsrs_COMPILER_MSVC_VERSION (_MSC_VER / 10 - 10 * ( 5 + (_MSC_VER < 1900 ) ) )
97 #else
98 # define nsrs_COMPILER_MSVC_VER 0
99 # define nsrs_COMPILER_MSVC_VERSION 0
100 #endif
101
102 #define nsrs_COMPILER_VERSION( major, minor, patch ) ( 10 * ( 10 * major + minor ) + patch )
103
104 #if defined(__clang__)
105 # define nsrs_COMPILER_CLANG_VERSION nsrs_COMPILER_VERSION( __clang_major__, __clang_minor__, __clang_patchlevel__ )
106 #else
107 # define nsrs_COMPILER_CLANG_VERSION 0
108 #endif
109
110 #if defined(__GNUC__) && !defined(__clang__)
111 # define nsrs_COMPILER_GNUC_VERSION nsrs_COMPILER_VERSION( __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__ )
112 #else
113 # define nsrs_COMPILER_GNUC_VERSION 0
114 #endif
115
116 // half-open range [lo..hi):
117 //#define nsrs_BETWEEN( v, lo, hi ) ( (lo) <= (v) && (v) < (hi) )
118
119 // Presence of language and library features:
120
121 #ifdef _HAS_CPP0X
122 # define nsrs_HAS_CPP0X _HAS_CPP0X
123 #else
124 # define nsrs_HAS_CPP0X 0
125 #endif
126
127 // Unless defined otherwise below, consider VC14 as C++11 for ring-span-lite:
128
129 #if nsrs_COMPILER_MSVC_VER >= 1900
130 # undef nsrs_CPP11_OR_GREATER
131 # define nsrs_CPP11_OR_GREATER 1
132 #endif
133
134 #define nsrs_CPP11_90 (nsrs_CPP11_OR_GREATER_ || nsrs_COMPILER_MSVC_VER >= 1500)
135 #define nsrs_CPP11_100 (nsrs_CPP11_OR_GREATER_ || nsrs_COMPILER_MSVC_VER >= 1600)
136 #define nsrs_CPP11_110 (nsrs_CPP11_OR_GREATER_ || nsrs_COMPILER_MSVC_VER >= 1700)
137 #define nsrs_CPP11_120 (nsrs_CPP11_OR_GREATER_ || nsrs_COMPILER_MSVC_VER >= 1800)
138 #define nsrs_CPP11_140 (nsrs_CPP11_OR_GREATER_ || nsrs_COMPILER_MSVC_VER >= 1900)
139
140 #define nsrs_CPP14_000 (nsrs_CPP14_OR_GREATER)
141 #define nsrs_CPP17_000 (nsrs_CPP17_OR_GREATER)
142
143 // Presence of C++11 language features:
144
145 // half-open range [lo..hi):
146 #define nsrs_BETWEEN( v, lo, hi ) ( (lo) <= (v) && (v) < (hi) )
147
148 // Presence of C++11 language features:
149
150 #define nsrs_HAVE_CONSTEXPR_11 nsrs_CPP11_140
151 #define nsrs_HAVE_IS_DEFAULT nsrs_CPP11_140
152 #define nsrs_HAVE_IS_DELETE nsrs_CPP11_140
153 #define nsrs_HAVE_NOEXCEPT nsrs_CPP11_140
154 #define nsrs_HAVE_NULLPTR nsrs_CPP11_100
155
156 // Presence of C++14 language features:
157
158 #define nsrs_HAVE_CONSTEXPR_14 nsrs_CPP14_000
159
160 // Presence of C++17 language features:
161 // no tag
162
163 // Presence of C++ library features:
164 // no tag
165
166 // Compiler warning suppression:
167
168 #if defined(__clang__)
169 # pragma clang diagnostic push
170 # pragma clang diagnostic ignored "-Wundef"
171 # define nsrs_RESTORE_WARNINGS() _Pragma( "clang diagnostic pop" )
172
173 #elif defined __GNUC__
174 # pragma GCC diagnostic push
175 # pragma GCC diagnostic ignored "-Wundef"
176 # define nsrs_RESTORE_WARNINGS() _Pragma( "GCC diagnostic pop" )
177
178 #elif nsrs_COMPILER_MSVC_VERSION >= 140
179 # define nsrs_DISABLE_MSVC_WARNINGS(codes) __pragma(warning(push)) __pragma(warning(disable: codes))
180 # define nsrs_RESTORE_WARNINGS() __pragma(warning(pop ))
181
182 // Suppress the following MSVC warnings:
183 // - C4345: initialization behavior changed
184 //
185 // Suppress the following MSVC GSL warnings:
186 // - C26439, gsl::f.6 : special function 'function' can be declared 'noexcept'
187 // - C26440, gsl::f.6 : function 'function' can be declared 'noexcept'
188 // - C26472, gsl::t.1 : don't use a static_cast for arithmetic conversions;
189 // use brace initialization, gsl::narrow_cast or gsl::narrow
190 // - C26473: gsl::t.1 : don't cast between pointer types where the source type and the target type are the same
191 // - C26481: gsl::b.1 : don't use pointer arithmetic. Use span instead
192 // - C26490: gsl::t.1 : don't use reinterpret_cast
193
194 nsrs_DISABLE_MSVC_WARNINGS( 4345 26439 26440 26472 26473 26481 26490 )
195
196 #else
197 # define nsrs_RESTORE_WARNINGS() /*empty*/
198 #endif
199
200 // C++ feature usage:
201
202 #if nsrs_HAVE_CONSTEXPR_11
203 # define nsrs_constexpr constexpr
204 #else
205 # define nsrs_constexpr /*constexpr*/
206 #endif
207
208 #if nsrs_HAVE_CONSTEXPR_14
209 # define nsrs_constexpr14 constexpr
210 #else
211 # define nsrs_constexpr14 /*constexpr*/
212 #endif
213
214 #if nsrs_HAVE_NOEXCEPT
215 # define nsrs_noexcept noexcept
216 # define nsrs_noexcept_op noexcept
217 #else
218 # define nsrs_noexcept /*noexcept*/
219 # define nsrs_noexcept_op(expr) /*noexcept(expr)*/
220 #endif
221
222 #if nsrs_HAVE_NULLPTR
223 # define nsrs_nullptr nullptr
224 #else
225 # define nsrs_nullptr NULL
226 #endif
227
228 // includes:
229
230 #include <cassert>
231 #include <iterator>
232 #include <utility>
233
234 // additional includes:
235
236 #if ! nsrs_CPP11_OR_GREATER
237 # include <algorithm> // std::swap() until C++11
238 #endif
239
240 namespace nonstd {
241
242 #if nsrs_CPP11_OR_GREATER
243 using std::move;
244 #else
245 template< typename T > T const & move( T const & t ) { return t; }
246 #endif
247
248 template< bool B, class T, class F >
249 struct conditional { typedef T type; };
250
251 template< class T, class F >
252 struct conditional<false, T, F> { typedef F type; };
253
254 #if nsrs_CPP11_OR_GREATER
255
256 template< bool B, class T, class F >
257 using conditional_t = typename conditional<B,T,F>::type;
258
259 template< bool B, class T = void >
260 using enable_if_t = typename std::enable_if<B,T>::type;
261
262 #endif
263
264 //
265 // element extraction policies:
266 //
267
268 template< class T >
269 struct null_popper
270 {
271 typedef void return_type;
272
operator ()nonstd::null_popper273 void operator()( T & ) const nsrs_noexcept {}
274 };
275
276 template< class T >
277 struct default_popper
278 {
279 typedef T return_type;
280
operator ()nonstd::default_popper281 T operator()( T & t ) const
282 {
283 return nonstd::move( t );
284 }
285 };
286
287 template< class T >
288 struct copy_popper
289 {
290 typedef T return_type;
291
292 #if nsrs_RING_SPAN_LITE_EXTENSION
293 # if nsrs_CPP11_OR_GREATER
copy_poppernonstd::copy_popper294 copy_popper( T t )
295 : m_copy( std::move(t) )
296 {}
297 # else
copy_poppernonstd::copy_popper298 copy_popper( T const & t )
299 : m_copy( t )
300 {}
301 # endif
302 #else
copy_poppernonstd::copy_popper303 copy_popper( T && t )
304 : copy( std::move(t) )
305 {}
306 #endif
307
operator ()nonstd::copy_popper308 T operator()( T & t ) const
309 {
310 using std::swap;
311 T result( m_copy ); swap( t, result ); return result;
312 }
313
314 T m_copy;
315 };
316
317 // forward-declare iterator:
318
319 namespace ring_detail {
320
321 template< class, bool >
322 class ring_iterator;
323
324 }
325
326 //
327 // ring span:
328 //
329 template< class T, class Popper = default_popper<T> >
330 class ring_span
331 {
332 public:
333 typedef T value_type;
334 typedef T * pointer;
335 typedef T & reference;
336 typedef T const & const_reference;
337
338 typedef std::size_t size_type;
339
340 typedef ring_span< T, Popper > type;
341
342 typedef ring_detail::ring_iterator< type, false > iterator;
343 typedef ring_detail::ring_iterator< type, true > const_iterator;
344
345 #if nsrs_RING_SPAN_LITE_EXTENSION
346 typedef std::reverse_iterator<iterator > reverse_iterator;
347 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
348 #endif
349
350 // construction:
351
352 template< class ContiguousIterator >
ring_span(ContiguousIterator begin,ContiguousIterator end,Popper popper=Popper ())353 ring_span(
354 ContiguousIterator begin
355 , ContiguousIterator end
356 , Popper popper = Popper()
357 ) nsrs_noexcept
358 : m_data ( &* begin )
359 , m_size ( 0 )
360 , m_capacity ( static_cast<size_type>( end - begin ) )
361 , m_front_idx( 0 )
362 , m_popper ( nonstd::move( popper ) )
363 {}
364
365 template< class ContiguousIterator >
ring_span(ContiguousIterator begin,ContiguousIterator end,ContiguousIterator first,size_type size,Popper popper=Popper ())366 ring_span(
367 ContiguousIterator begin
368 , ContiguousIterator end
369 , ContiguousIterator first
370 , size_type size
371 , Popper popper = Popper()
372 ) nsrs_noexcept
373 : m_data ( &* begin )
374 , m_size ( size )
375 , m_capacity ( static_cast<size_type>( end - begin ) )
376 , m_front_idx( static_cast<size_type>( first - begin ) )
377 , m_popper ( nonstd::move( popper ) )
378 {}
379
380 #if nsrs_HAVE_IS_DEFAULT
381 ring_span( ring_span && ) = default;
382 ring_span& operator=( ring_span && ) = default;
383 #else
384 private:
385 ring_span( ring_span const & );
386 ring_span & operator=( ring_span const & );
387 public:
388 #endif
389
390 // observers:
391
empty() const392 bool empty() const nsrs_noexcept
393 {
394 return m_size == 0;
395 }
396
full() const397 bool full() const nsrs_noexcept
398 {
399 return m_size == m_capacity;
400 }
401
size() const402 size_type size() const nsrs_noexcept
403 {
404 return m_size;
405 }
406
capacity() const407 size_type capacity() const nsrs_noexcept
408 {
409 return m_capacity;
410 }
411
412 // element access:
413
front()414 reference front() nsrs_noexcept
415 {
416 return *begin();
417 }
418
front() const419 const_reference front() const nsrs_noexcept
420 {
421 return *begin();
422 }
423
back()424 reference back() nsrs_noexcept
425 {
426 return *(--end());
427 }
428
back() const429 const_reference back() const nsrs_noexcept
430 {
431 return *(--end());
432 }
433
434 // iteration:
435
begin()436 iterator begin() nsrs_noexcept
437 {
438 return iterator( 0, this );
439 }
440
begin() const441 const_iterator begin() const nsrs_noexcept
442 {
443 return cbegin();
444 }
445
cbegin() const446 const_iterator cbegin() const nsrs_noexcept
447 {
448 return const_iterator( 0, this );
449 }
450
end()451 iterator end() nsrs_noexcept
452 {
453 return iterator( size(), this );
454 }
455
end() const456 const_iterator end() const nsrs_noexcept
457 {
458 return cend();
459 }
460
cend() const461 const_iterator cend() const nsrs_noexcept
462 {
463 return const_iterator( size(), this );
464 }
465
466 #if nsrs_RING_SPAN_LITE_EXTENSION
467
rbegin()468 reverse_iterator rbegin() nsrs_noexcept
469 {
470 return reverse_iterator( end() );
471 }
472
rend()473 reverse_iterator rend() nsrs_noexcept
474 {
475 return reverse_iterator( begin() );
476 }
477
rbegin() const478 const_reverse_iterator rbegin() const nsrs_noexcept
479 {
480 return crbegin();
481 }
482
rend() const483 const_reverse_iterator rend() const nsrs_noexcept
484 {
485 return crend();
486 }
487
crbegin() const488 const_reverse_iterator crbegin() const nsrs_noexcept
489 {
490 return const_reverse_iterator( cend() );
491 }
492
crend() const493 const_reverse_iterator crend() const nsrs_noexcept
494 {
495 return const_reverse_iterator(cbegin());
496 }
497 #endif
498
erase_from(iterator first)499 void erase_from(iterator first) {
500 m_size = static_cast<size_type>(std::distance(begin(), first));
501 }
502
503 // element insertion, extraction:
504
pop_front()505 typename Popper::return_type pop_front()
506 {
507 assert( ! empty() );
508
509 reference element = front_();
510 increment_front_();
511
512 return m_popper( element );
513 }
514
515 #if nsrs_RING_SPAN_LITE_EXTENSION
pop_back()516 typename Popper::return_type pop_back()
517 {
518 assert( ! empty() );
519
520 reference element = back_();
521 decrement_back_();
522
523 return m_popper( element );
524 }
525 #endif
526
527 #if nsrs_CPP11_OR_GREATER
528 template< bool b = true, typename = nonstd::enable_if_t<b && std::is_copy_assignable<T>::value> >
push_back(value_type const & value)529 void push_back( value_type const & value) nsrs_noexcept_op(( std::is_nothrow_copy_assignable<T>::value ))
530 #else
531 void push_back( value_type const & value )
532 #endif
533 {
534 if ( full() ) increment_front_and_back_();
535 else increment_back_();
536
537 back_() = value;
538 }
539
540 #if nsrs_CPP11_OR_GREATER
541 template< bool b = true, typename = nonstd::enable_if_t<b && std::is_move_assignable<T>::value> >
push_back(value_type && value)542 void push_back( value_type && value ) nsrs_noexcept_op(( std::is_nothrow_move_assignable<T>::value ))
543 {
544 if ( full() ) increment_front_and_back_();
545 else increment_back_();
546
547 back_() = std::move( value );
548 }
549
550 template< class... Args >
emplace_back(Args &&...args)551 void emplace_back( Args &&... args )
552 nsrs_noexcept_op(( std::is_nothrow_constructible<T, Args...>::value && std::is_nothrow_move_assignable<T>::value ))
553 {
554 if ( full() ) increment_front_and_back_();
555 else increment_back_();
556
557 back_() = T( std::forward<Args>(args)...);
558 }
559 #endif
560
561 #if nsrs_RING_SPAN_LITE_EXTENSION
562
563 #if nsrs_CPP11_OR_GREATER
564 template<bool b = true, typename = nonstd::enable_if_t<b && std::is_copy_assignable<T>::value> >
push_front(T const & value)565 void push_front( T const & value ) nsrs_noexcept_op(( std::is_nothrow_copy_assignable<T>::value ))
566 #else
567 void push_front( T const & value )
568 #endif
569 {
570 if ( full() ) decrement_front_and_back_();
571 else decrement_front_();
572
573 front_() = value;
574 }
575
576 #if nsrs_CPP11_OR_GREATER
577 template<bool b = true, typename = nonstd::enable_if_t<b && std::is_move_assignable<T>::value> >
push_front(T && value)578 void push_front( T && value ) nsrs_noexcept_op(( std::is_nothrow_move_assignable<T>::value ))
579 {
580 if ( full() ) decrement_front_and_back_();
581 else decrement_front_();
582
583 front_() = std::move(value);
584 }
585
586 template<typename... Args>
emplace_front(Args &&...args)587 void emplace_front( Args&&... args )
588 nsrs_noexcept_op(( std::is_nothrow_constructible<T, Args...>::value && std::is_nothrow_move_assignable<T>::value ))
589 {
590 if ( full() ) decrement_front_and_back_();
591 else decrement_front_();
592
593 front_() = T( std::forward<Args>(args)...);
594 }
595 #endif
596 #endif // nsrs_RING_SPAN_LITE_EXTENSION
597
598 // swap:
599
swap(type & rhs)600 void swap( type & rhs ) nsrs_noexcept // nsrs_noexcept_op(std::is_nothrow_swappable<Popper>::value);
601 {
602 using std::swap;
603 swap( m_data , rhs.m_data );
604 swap( m_size , rhs.m_size );
605 swap( m_capacity , rhs.m_capacity );
606 swap( m_front_idx, rhs.m_front_idx );
607 swap( m_popper , rhs.m_popper );
608 }
609
610 private:
611 friend class ring_detail::ring_iterator<ring_span, true >; // const_iterator;
612 friend class ring_detail::ring_iterator<ring_span, false>; // iterator;
613
normalize_(size_type const idx) const614 size_type normalize_( size_type const idx ) const nsrs_noexcept
615 {
616 return idx % m_capacity;
617 }
618
at(size_type idx)619 reference at( size_type idx ) nsrs_noexcept
620 {
621 return m_data[ normalize_(m_front_idx + idx) ];
622 }
623
at(size_type idx) const624 const_reference at( size_type idx ) const nsrs_noexcept
625 {
626 return m_data[ normalize_(m_front_idx + idx) ];
627 }
628
front_()629 reference front_() nsrs_noexcept
630 {
631 return *( m_data + m_front_idx );
632 }
633
front_() const634 const_reference front_() const nsrs_noexcept
635 {
636 return *( m_data + m_front_idx );
637 }
638
back_()639 reference back_() nsrs_noexcept
640 {
641 return *( m_data + normalize_(m_front_idx + m_size - 1) );
642 }
643
back_() const644 const_reference back_() const nsrs_noexcept
645 {
646 return *( m_data + normalize_(m_front_idx + m_size - 1) );
647 }
648
increment_front_()649 void increment_front_() nsrs_noexcept
650 {
651 m_front_idx = normalize_(m_front_idx + 1);
652 --m_size;
653 }
654
decrement_front_()655 void decrement_front_() nsrs_noexcept
656 {
657 m_front_idx = normalize_(m_front_idx + m_capacity - 1);
658 ++m_size;
659 }
660
increment_back_()661 void increment_back_() nsrs_noexcept
662 {
663 ++m_size;
664 }
665
decrement_back_()666 void decrement_back_() nsrs_noexcept
667 {
668 --m_size;
669 }
670
increment_front_and_back_()671 void increment_front_and_back_() nsrs_noexcept
672 {
673 m_front_idx = normalize_( m_front_idx + 1 );
674 }
675
decrement_front_and_back_()676 void decrement_front_and_back_() nsrs_noexcept
677 {
678 m_front_idx = normalize_( m_front_idx + m_capacity - 1 );
679 }
680
681 private:
682 pointer m_data;
683 size_type m_size;
684 size_type m_capacity;
685 size_type m_front_idx;
686 Popper m_popper;
687 };
688
689 // swap:
690
691 template< class T, class Popper >
swap(ring_span<T,Popper> & lhs,ring_span<T,Popper> & rhs)692 inline void swap( ring_span<T,Popper> & lhs, ring_span<T,Popper> & rhs ) nsrs_noexcept_op( nsrs_noexcept_op( lhs.swap(rhs) ) )
693 {
694 lhs.swap(rhs);
695 }
696
697 namespace ring_detail {
698
699 //
700 // ring iterator:
701 //
702 #if 0
703 template< class RS, bool is_const >
704 class ring_iterator : public std::iterator
705 <
706 std::random_access_iterator_tag
707 , typename nonstd::conditional<is_const, const typename RS::value_type, typename RS::value_type>::type
708 >
709 #endif
710
711 template< class RS, bool is_const >
712 class ring_iterator
713 {
714 public:
715 typedef ring_iterator<RS, is_const> type;
716
717 typedef std::ptrdiff_t difference_type;
718 typedef typename RS::value_type value_type;
719
720 typedef typename nonstd::conditional<is_const, const value_type, value_type>::type * pointer;
721 typedef typename nonstd::conditional<is_const, const value_type, value_type>::type & reference;
722 typedef std::random_access_iterator_tag iterator_category;
723
724 #if nsrs_CPP11_OR_GREATER
725 ring_iterator() = default;
726 #else
ring_iterator()727 ring_iterator() : m_idx(), m_rs() {}
728 #endif
729
730 #if nsrs_RING_SPAN_LITE_EXTENSION
731 // conversion to const iterator:
732
operator ring_iterator<RS,true>() const733 operator ring_iterator<RS, true>() const nsrs_noexcept
734 {
735 return ring_iterator<RS, true>( m_idx, m_rs );
736 }
737 #endif
738
739 // access content:
740
operator *() const741 reference operator*() const nsrs_noexcept
742 {
743 return m_rs->at( m_idx );
744 }
745
746 // advance iterator:
747
operator ++()748 type & operator++() nsrs_noexcept
749 {
750 ++m_idx; return *this;
751 }
752
operator ++(int)753 type operator++( int ) nsrs_noexcept
754 {
755 type r(*this); ++*this; return r;
756 }
757
operator --()758 type & operator--() nsrs_noexcept
759 {
760 --m_idx; return *this;
761 }
762
operator --(int)763 type operator--( int ) nsrs_noexcept
764 {
765 type r(*this); --*this; return r;
766 }
767
768 #if defined(__clang__) || defined(__GNUC__)
769 # pragma GCC diagnostic push
770 # pragma GCC diagnostic ignored "-Wsign-conversion"
771 #endif
772
operator +=(int i)773 type & operator+=( int i ) nsrs_noexcept
774 {
775 m_idx += i; return *this;
776 }
777
operator -=(int i)778 type & operator-=( int i ) nsrs_noexcept
779 {
780 m_idx -= i; return *this;
781 }
782
783 #if defined(__clang__) || defined(__GNUC__)
784 # pragma GCC diagnostic pop
785 #endif
786
787 #if nsrs_RING_SPAN_LITE_EXTENSION
788
789 template< bool C >
operator -(ring_iterator<RS,C> const & rhs) const790 difference_type operator-( ring_iterator<RS,C> const & rhs ) const nsrs_noexcept
791 {
792 return static_cast<difference_type>( this->m_idx ) - static_cast<difference_type>( rhs.m_idx );
793 }
794 #endif
795
796 // comparison:
797
798 template< bool C >
operator <(ring_iterator<RS,C> const & rhs) const799 bool operator<( ring_iterator<RS,C> const & rhs ) const nsrs_noexcept
800 {
801 assert( this->m_rs == rhs.m_rs ); return ( this->m_idx < rhs.m_idx );
802 }
803
804 template< bool C >
operator ==(ring_iterator<RS,C> const & rhs) const805 bool operator==( ring_iterator<RS,C> const & rhs ) const nsrs_noexcept
806 {
807 assert( this->m_rs == rhs.m_rs ); return ( this->m_idx == rhs.m_idx );
808 }
809
810 // other comparisons expressed in <, ==:
811
812 template< bool C >
operator !=(ring_iterator<RS,C> const & rhs) const813 inline bool operator!=( ring_iterator<RS,C> const & rhs ) const nsrs_noexcept
814 {
815 return ! ( *this == rhs );
816 }
817
818 template< bool C >
operator <=(ring_iterator<RS,C> const & rhs) const819 inline bool operator<=( ring_iterator<RS,C> const & rhs ) const nsrs_noexcept
820 {
821 return ! ( rhs < *this );
822 }
823
824 template< bool C >
operator >(ring_iterator<RS,C> const & rhs) const825 inline bool operator>( ring_iterator<RS,C> const & rhs ) const nsrs_noexcept
826 {
827 return rhs < *this;
828 }
829
830 template< bool C >
operator >=(ring_iterator<RS,C> const & rhs) const831 inline bool operator>=( ring_iterator<RS,C> const & rhs ) const nsrs_noexcept
832 {
833 return ! ( *this < rhs );
834 }
835
836 private:
837 friend RS; // clang: non-class friend type 'RS' is a C++11 extension [-Wc++11-extensions]
838 friend class ring_iterator<RS, ! is_const>;
839
840 typedef typename RS::size_type size_type;
841 typedef typename nonstd::conditional<is_const, const RS, RS>::type ring_type;
842
ring_iterator(size_type idx,typename nonstd::conditional<is_const,const RS,RS>::type * rs)843 ring_iterator( size_type idx, typename nonstd::conditional<is_const, const RS, RS>::type * rs ) nsrs_noexcept
844 : m_idx( idx )
845 , m_rs ( rs )
846 {}
847
848 private:
849 size_type m_idx;
850 ring_type * m_rs;
851 };
852
853 // advanced iterator:
854
855 template< class RS, bool C >
operator +(ring_iterator<RS,C> it,int i)856 inline ring_iterator<RS,C> operator+( ring_iterator<RS,C> it, int i ) nsrs_noexcept
857 {
858 it += i; return it;
859 }
860
861 template< class RS, bool C >
operator -(ring_iterator<RS,C> it,int i)862 inline ring_iterator<RS,C> operator-( ring_iterator<RS,C> it, int i ) nsrs_noexcept
863 {
864 it -= i; return it;
865 }
866
867 } // namespace detail
868 } // namespace nonstd
869
870 nsrs_RESTORE_WARNINGS()
871
872 #endif // NONSTD_RING_SPAN_LITE_HPP
873