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