text: //
  // Copyright (c) 2015 Arthur O'Dwyer
  // Copyright 2017-2018 by Martin Moene
  //
  // https://github.com/martinmoene/ring-span-lite
  //
  // Distributed under the Boost Software License, Version 1.0.
  // (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  
  #pragma once
  
  #ifndef stdext_RING_SPAN_LITE_HPP
  #define stdext_RING_SPAN_LITE_HPP
  
  #include <cassert>
  #include <iterator>
  #include <utility>
  
  #define ring_span_lite_MAJOR  0
  #define ring_span_lite_MINOR  2
  #define ring_span_lite_PATCH  0
  
  #define ring_span_lite_VERSION  ring_span_STRINGIFY(ring_span_lite_MAJOR) "." ring_span_STRINGIFY(ring_span_lite_MINOR) "." ring_span_STRINGIFY(ring_span_lite_PATCH)
  
  #define ring_span_STRINGIFY(  x )  ring_span_STRINGIFY_( x )
  #define ring_span_STRINGIFY_( x )  #x
  
  // ring-span-lite configuration:
  
  #ifndef  nsrs_CONFIG_STRICT_P0059
  # define nsrs_CONFIG_STRICT_P0059  0
  #endif
  
  #define nsrs_RING_SPAN_LITE_EXTENSION  (! nsrs_CONFIG_STRICT_P0059)
  
  // Compiler detection (C++20 is speculative):
  // Note: MSVC supports C++14 in full since it supports C++17.
  
  #ifdef _MSVC_LANG
  # define nsrs_MSVC_LANG _MSVC_LANG
  #else
  # define nsrs_MSVC_LANG 0
  #endif
  
  #define nsrs_CPP11_OR_GREATER ( __cplusplus >= 201103L || nsrs_MSVC_LANG >= 201103L )
  #define nsrs_CPP14_OR_GREATER ( __cplusplus >= 201402L || nsrs_MSVC_LANG >= 201402L /*201703L*/ )
  #define nsrs_CPP17_OR_GREATER ( __cplusplus >= 201703L || nsrs_MSVC_LANG >= 201703L )
  #define nsrs_CPP20_OR_GREATER ( __cplusplus >= 202000L || nsrs_MSVC_LANG >= 202000L )
  
  // Compiler versions:
  //
  // MSVC++ 6.0  _MSC_VER == 1200 (Visual Studio 6.0)
  // MSVC++ 7.0  _MSC_VER == 1300 (Visual Studio .NET 2002)
  // MSVC++ 7.1  _MSC_VER == 1310 (Visual Studio .NET 2003)
  // MSVC++ 8.0  _MSC_VER == 1400 (Visual Studio 2005)
  // MSVC++ 9.0  _MSC_VER == 1500 (Visual Studio 2008)
  // MSVC++ 10.0 _MSC_VER == 1600 (Visual Studio 2010)
  // MSVC++ 11.0 _MSC_VER == 1700 (Visual Studio 2012)
  // MSVC++ 12.0 _MSC_VER == 1800 (Visual Studio 2013)
  // MSVC++ 14.0 _MSC_VER == 1900 (Visual Studio 2015)
  // ............_MSVC_LANG: 201402 for -std:c++14, default
  // MSVC++ 14.1 _MSC_VER >= 1910 (Visual Studio 2017)
  // ............_MSVC_LANG: 201402 for -std:c++14, default
  // ............_MSVC_LANG: 201703 for -std:c++17
  
  #if defined( _MSC_VER ) && !defined( __clang__ )
  # define nsrs_COMPILER_MSVC_VERSION ( _MSC_VER / 10 - 10 * ( 5 + ( _MSC_VER < 1900 ) ) )
  #else
  # define nsrs_COMPILER_MSVC_VERSION 0
  #endif
  
  #define nsrs_COMPILER_VERSION( major, minor, patch ) ( 10 * ( 10 * major + minor ) + patch )
  
  #if defined(__clang__)
  # define nsrs_COMPILER_CLANG_VERSION nsrs_COMPILER_VERSION( __clang_major__, __clang_minor__, __clang_patchlevel__ )
  #else
  # define nsrs_COMPILER_CLANG_VERSION 0
  #endif
  
  #if defined(__GNUC__) && !defined(__clang__)
  # define nsrs_COMPILER_GNUC_VERSION nsrs_COMPILER_VERSION( __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__ )
  #else
  # define nsrs_COMPILER_GNUC_VERSION 0
  #endif
  
  // Compiler warning suppression:
  
  #if defined(__clang__)
  # pragma clang diagnostic push
  # pragma clang diagnostic ignored "-Wundef"
  # define nsrs_RESTORE_WARNINGS()   _Pragma( "clang diagnostic pop" )
  
  #elif defined __GNUC__
  # pragma GCC   diagnostic push
  # pragma GCC   diagnostic ignored "-Wundef"
  # define nsrs_RESTORE_WARNINGS()   _Pragma( "GCC diagnostic pop" )
  
  #elif nsrs_COMPILER_MSVC_VERSION >= 140
  # define nsrs_DISABLE_MSVC_WARNINGS(codes)  __pragma(warning(push))  __pragma(warning(disable: codes))
  # define nsrs_RESTORE_WARNINGS()            __pragma(warning(pop ))
  
  // Suppress the following MSVC warnings:
  // - C4345: initialization behavior changed
  //
  // Suppress the following MSVC GSL warnings:
  // - C26439, gsl::f.6 : special function 'function' can be declared 'noexcept'
  // - C26440, gsl::f.6 : function 'function' can be declared 'noexcept'
  // - C26472, gsl::t.1 : don't use a static_cast for arithmetic conversions;
  //                      use brace initialization, gsl::narrow_cast or gsl::narrow
  // - C26473: gsl::t.1 : don't cast between pointer types where the source type and the target type are the same
  // - C26481: gsl::b.1 : don't use pointer arithmetic. Use span instead
  // - C26490: gsl::t.1 : don't use reinterpret_cast
  
  nsrs_DISABLE_MSVC_WARNINGS( 4345 26439 26440 26472 26473 26481 26490 )
  
  #else
  # define nsrs_RESTORE_WARNINGS()  /*empty*/
  #endif
  
  // half-open range [lo..hi):
  #define nsrs_BETWEEN( v, lo, hi ) ( lo <= v && v < hi )
  
  // Presence of C++11 language features:
  
  #if nsrs_CPP11_OR_GREATER || nsrs_COMPILER_MSVC_VERSION >= 100
  # define nsrs_HAVE_AUTO  1
  # define nsrs_HAVE_NULLPTR  1
  # define nsrs_HAVE_STATIC_ASSERT  1
  #endif
  
  #if nsrs_CPP11_OR_GREATER || nsrs_COMPILER_MSVC_VERSION >= 120
  # define nsrs_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG  1
  # define nsrs_HAVE_INITIALIZER_LIST  1
  #endif
  
  #if nsrs_CPP11_OR_GREATER || nsrs_COMPILER_MSVC_VERSION >= 140
  # define nsrs_HAVE_ALIAS_TEMPLATE  1
  # define nsrs_HAVE_CONSTEXPR_11  1
  # define nsrs_HAVE_ENUM_CLASS  1
  # define nsrs_HAVE_EXPLICIT_CONVERSION  1
  # define nsrs_HAVE_IS_DEFAULT  1
  # define nsrs_HAVE_IS_DELETE  1
  # define nsrs_HAVE_NOEXCEPT  1
  #endif
  
  // Presence of C++14 language features:
  
  #if nsrs_CPP14_OR_GREATER
  # define nsrs_HAVE_CONSTEXPR_14  1
  #endif
  
  // Presence of C++17 language features:
  
  #if nsrs_CPP17_OR_GREATER
  # define nsrs_HAVE_ENUM_CLASS_CONSTRUCTION_FROM_UNDERLYING_TYPE  1
  #endif
  
  // Presence of C++ library features:
  
  #if nsrs_COMPILER_GNUC_VERSION
  # define nsrs_HAVE_TR1_TYPE_TRAITS  1
  # define nsrs_HAVE_TR1_ADD_POINTER  1
  #endif
  
  #if nsrs_CPP11_OR_GREATER || nsrs_COMPILER_MSVC_VERSION >= 90
  # define nsrs_HAVE_TYPE_TRAITS  1
  # define nsrs_HAVE_STD_ADD_POINTER  1
  #endif
  
  #if nsrs_CPP11_OR_GREATER || nsrs_COMPILER_MSVC_VERSION >= 110
  # define nsrs_HAVE_ARRAY  1
  #endif
  
  #if nsrs_CPP11_OR_GREATER || nsrs_COMPILER_MSVC_VERSION >= 120
  # define nsrs_HAVE_CONDITIONAL  1
  #endif
  
  #if nsrs_CPP11_OR_GREATER || nsrs_COMPILER_MSVC_VERSION >= 140 || (nsrs_COMPILER_MSVC_VERSION >= 90 && _HAS_CPP0X)
  # define nsrs_HAVE_CONTAINER_DATA_METHOD  1
  #endif
  
  #if nsrs_CPP11_OR_GREATER || nsrs_COMPILER_MSVC_VERSION >= 120
  # define nsrs_HAVE_REMOVE_CV  1
  #endif
  
  #if nsrs_CPP11_OR_GREATER || nsrs_COMPILER_MSVC_VERSION >= 140
  # define nsrs_HAVE_SIZED_TYPES  1
  #endif
  
  // For the rest, consider VC14 as C++11 for ring-span-lite:
  
  #if nsrs_COMPILER_MSVC_VERSION >= 140
  # undef  nsrs_CPP11_OR_GREATER
  # define nsrs_CPP11_OR_GREATER  1
  #endif
  
  // C++ feature usage:
  
  #if nsrs_HAVE_CONSTEXPR_11
  # define nsrs_constexpr constexpr
  #else
  # define nsrs_constexpr /*constexpr*/
  #endif
  
  #if nsrs_HAVE_CONSTEXPR_14
  # define nsrs_constexpr14 constexpr
  #else
  # define nsrs_constexpr14 /*constexpr*/
  #endif
  
  #if nsrs_HAVE_NOEXCEPT
  # define nsrs_noexcept noexcept
  # define nsrs_noexcept_op noexcept
  #else
  # define nsrs_noexcept /*noexcept*/
  # define nsrs_noexcept_op(expr) /*noexcept(expr)*/
  #endif
  
  #if nsrs_HAVE_NULLPTR
  # define nsrs_nullptr nullptr
  #else
  # define nsrs_nullptr NULL
  #endif
  
  // additional includes:
  
  #if ! nsrs_CPP11_OR_GREATER
  # include <algorithm>           // std::swap() until C++11
  #endif
  
  #if nsrs_HAVE_INITIALIZER_LIST
  # include <initializer_list>
  #endif
  
  #if nsrs_HAVE_TYPE_TRAITS
  # include <type_traits>
  #elif nsrs_HAVE_TR1_TYPE_TRAITS
  # include <tr1/type_traits>
  #endif
  
  namespace stdext {
  
  #if nsrs_CPP11_OR_GREATER
  using std::move;
  #else
  template< typename T > T const & move( T const & t ) { return t; }
  #endif
  
  template< bool B, class T, class F >
  struct conditional { typedef T type; };
  
  template< class T, class F >
  struct conditional<false, T, F> { typedef F type; };
  
  #if nsrs_CPP11_OR_GREATER
  
  template< bool B, class T, class F >
  using conditional_t = typename conditional<B,T,F>::type;
  
  template< bool B, class T = void >
  using enable_if_t = typename std::enable_if<B,T>::type;
  
  #endif
  
  //
  // element extraction policies:
  //
  
  template< class T >
  struct null_popper
  {
      typedef void return_type;
  
      void operator()( T & ) const nsrs_noexcept {}
  };
  
  template< class T >
  struct default_popper
  {
      typedef T return_type;
  
      T operator()( T & t ) const
      {
          return stdext::move( t );
      }
  };
  
  template< class T >
  struct copy_popper
  {
      typedef T return_type;
  
  #if  nsrs_RING_SPAN_LITE_EXTENSION
  # if nsrs_CPP11_OR_GREATER
      copy_popper( T t )
      : m_copy( std::move(t) )
      {}
  # else
      copy_popper( T const & t )
      : m_copy( t )
      {}
  # endif
  #else
      copy_popper( T && t )
      : copy( std::move(t) )
      {}
  #endif
  
      T operator()( T & t ) const
      {
          using std::swap;
          T result( m_copy ); swap( t, result ); return result;
      }
  
      T m_copy;
  };
  
  // forward-declare iterator:
  
  namespace detail {
  
  template< class, bool >
  class ring_iterator;
  
  }
  
  //
  // ring span:
  //
  template< class T, class Popper = default_popper<T> >
  class ring_span
  {
  public:
      typedef T   value_type;
      typedef T * pointer;
      typedef T & reference;
      typedef T const & const_reference;
  
      typedef std::size_t size_type;
  
      typedef ring_span< T, Popper > type;
  
      typedef detail::ring_iterator< type, false  > iterator;
      typedef detail::ring_iterator< type, true   > const_iterator;
  
  #if nsrs_RING_SPAN_LITE_EXTENSION
      typedef std::reverse_iterator<iterator      > reverse_iterator;
      typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
  #endif
  
      // construction:
  
      template< class ContiguousIterator >
      ring_span(
          ContiguousIterator   begin
          , ContiguousIterator end
          , Popper popper = Popper()
      ) nsrs_noexcept
      : m_data     ( &* begin )
      , m_size     ( 0 )
      , m_capacity ( static_cast<size_type>( end - begin ) )
      , m_front_idx( 0 )
      , m_popper   ( stdext::move( popper ) )
      {}
  
      template< class ContiguousIterator >
      ring_span(
          ContiguousIterator   begin
          , ContiguousIterator end
          , ContiguousIterator first
          , size_type          size
          , Popper popper = Popper()
      ) nsrs_noexcept
      : m_data     ( &* begin )
      , m_size     ( size     )
      , m_capacity ( static_cast<size_type>( end   - begin ) )
      , m_front_idx( static_cast<size_type>( first - begin ) )
      , m_popper   ( stdext::move( popper ) )
      {}
  
  #if nsrs_HAVE_IS_DEFAULT
      ring_span( ring_span && ) = default;
      ring_span& operator=( ring_span && ) = default;
  #else
  private:
      ring_span( ring_span const & );
      ring_span & operator=( ring_span const & );
  public:
  #endif
  
      // observers:
  
      bool empty() const nsrs_noexcept
      {
          return m_size == 0;
      }
  
      bool full() const nsrs_noexcept
      {
          return m_size == m_capacity;
      }
  
      size_type size() const nsrs_noexcept
      {
          return m_size;
      }
  
      size_type capacity() const nsrs_noexcept
      {
          return m_capacity;
      }
  
      // element access:
  
      reference front() nsrs_noexcept
      {
          return *begin();
      }
  
      const_reference front() const nsrs_noexcept
      {
          return *begin();
      }
  
      reference back() nsrs_noexcept
      {
          return *(--end());
      }
  
      const_reference back() const nsrs_noexcept
      {
          return *(--end());
      }
  
      // iteration:
  
      iterator begin() nsrs_noexcept
      {
          return iterator( 0, this );
      }
  
      const_iterator begin() const nsrs_noexcept
      {
          return cbegin();
      }
  
      const_iterator cbegin() const nsrs_noexcept
      {
          return const_iterator( 0, this );
      }
  
      iterator end() nsrs_noexcept
      {
          return iterator( size(), this );
      }
  
      const_iterator end() const nsrs_noexcept
      {
          return cend();
      }
  
      const_iterator cend() const nsrs_noexcept
      {
          return const_iterator( size(), this );
      }
  
  #if nsrs_RING_SPAN_LITE_EXTENSION
  
      reverse_iterator rbegin() nsrs_noexcept
      {
          return reverse_iterator( end() );
      }
  
      reverse_iterator rend() nsrs_noexcept
      {
          return reverse_iterator( begin() );
      }
  
      const_reverse_iterator rbegin() const nsrs_noexcept
      {
          return crbegin();
      }
  
      const_reverse_iterator rend() const nsrs_noexcept
      {
          return crend();
      }
  
      const_reverse_iterator crbegin() const nsrs_noexcept
      {
          return const_reverse_iterator( cend() );
      }
  
      const_reverse_iterator crend() const nsrs_noexcept
      {
          return const_reverse_iterator(cbegin());
      }
  #endif
  
      // element insertion, extraction:
  
      typename Popper::return_type pop_front()
      {
          assert( ! empty() );
  
          reference element = front_();
          increment_front_();
  
          return m_popper( element );
      }
  
  #if nsrs_RING_SPAN_LITE_EXTENSION
      typename Popper::return_type pop_back()
      {
          assert( ! empty() );
  
          reference element = back_();
          decrement_back_();
  
          return m_popper( element );
      }
  #endif
  
  #if nsrs_CPP11_OR_GREATER
      template< bool b = true, typename = stdext::enable_if_t<b && std::is_copy_assignable<T>::value> >
      void push_back( value_type const & value) nsrs_noexcept_op(( std::is_nothrow_copy_assignable<T>::value ))
  #else
      void push_back( value_type const & value )
  #endif
      {
          if ( full() )  increment_front_and_back_();
          else           increment_back_();
  
          back_() = value;
      }
  
      void reserve(size_t n)
      {
          for(size_t i = 0; i < n; i++)
          {
              if ( full() )  increment_front_and_back_();
              else           increment_back_();
          }
      }
  
  #if nsrs_CPP11_OR_GREATER
      template< bool b = true, typename = stdext::enable_if_t<b && std::is_move_assignable<T>::value> >
      void push_back( value_type && value ) nsrs_noexcept_op(( std::is_nothrow_move_assignable<T>::value ))
      {
          if ( full() )  increment_front_and_back_();
          else           increment_back_();
  
          back_() = std::move( value );
      }
  
      template< class... Args >
      void emplace_back( Args &&... args )
          nsrs_noexcept_op(( std::is_nothrow_constructible<T, Args...>::value && std::is_nothrow_move_assignable<T>::value ))
      {
          if ( full() )  increment_front_and_back_();
          else           increment_back_();
  
          back_() = T( std::forward<Args>(args)...);
     }
  #endif
  
  #if nsrs_RING_SPAN_LITE_EXTENSION
  
  #if nsrs_CPP11_OR_GREATER
      template<bool b = true, typename = stdext::enable_if_t<b && std::is_copy_assignable<T>::value> >
      void push_front( T const & value ) nsrs_noexcept_op(( std::is_nothrow_copy_assignable<T>::value ))
  #else
      void push_front( T const & value )
  #endif
      {
          if ( full() ) decrement_front_and_back_();
          else          decrement_front_();
  
          front_() = value;
      }
  
  #if nsrs_CPP11_OR_GREATER
      template<bool b = true, typename = stdext::enable_if_t<b && std::is_move_assignable<T>::value> >
      void push_front( T && value ) nsrs_noexcept_op(( std::is_nothrow_move_assignable<T>::value ))
      {
          if ( full() ) decrement_front_and_back_();
          else          decrement_front_();
  
          front_() = std::move(value);
      }
  
      template<typename... Args>
      void emplace_front( Args&&... args )
          nsrs_noexcept_op(( std::is_nothrow_constructible<T, Args...>::value && std::is_nothrow_move_assignable<T>::value ))
      {
          if ( full() ) decrement_front_and_back_();
          else          decrement_front_();
  
          front_() = T( std::forward<Args>(args)...);
      }
  #endif
  #endif // nsrs_RING_SPAN_LITE_EXTENSION
  
      // swap:
  
      void swap( type & rhs ) nsrs_noexcept // nsrs_noexcept_op(std::is_nothrow_swappable<Popper>::value);
      {
          using std::swap;
          swap( m_data     , rhs.m_data      );
          swap( m_size     , rhs.m_size      );
          swap( m_capacity , rhs.m_capacity  );
          swap( m_front_idx, rhs.m_front_idx );
          swap( m_popper   , rhs.m_popper    );
      }
  
  private:
      friend class detail::ring_iterator<ring_span, true >;   // const_iterator;
      friend class detail::ring_iterator<ring_span, false>;   // iterator;
  
      size_type normalize_( size_type const idx ) const nsrs_noexcept
      {
          return idx % m_capacity;
      }
  
      reference at( size_type idx ) nsrs_noexcept
      {
          return m_data[ normalize_(m_front_idx + idx) ];
      }
  
      const_reference at( size_type idx ) const nsrs_noexcept
      {
          return m_data[ normalize_(m_front_idx + idx) ];
      }
  
      reference front_() nsrs_noexcept
      {
          return *( m_data + m_front_idx );
      }
  
      const_reference front_() const nsrs_noexcept
      {
          return *( m_data + m_front_idx );
      }
  
      reference back_() nsrs_noexcept
      {
          return *( m_data + normalize_(m_front_idx + m_size - 1) );
      }
  
      const_reference back_() const nsrs_noexcept
      {
          return *( m_data + normalize_(m_front_idx + m_size - 1) );
      }
  
      void increment_front_() nsrs_noexcept
      {
          m_front_idx = normalize_(m_front_idx + 1);
          --m_size;
      }
  
      void decrement_front_() nsrs_noexcept
      {
          m_front_idx = normalize_(m_front_idx + m_capacity - 1);
          ++m_size;
      }
  
      void increment_back_() nsrs_noexcept
      {
          ++m_size;
      }
  
      void decrement_back_() nsrs_noexcept
      {
          --m_size;
      }
  
      void increment_front_and_back_() nsrs_noexcept
      {
          m_front_idx = normalize_( m_front_idx + 1 );
      }
  
      void decrement_front_and_back_() nsrs_noexcept
      {
          m_front_idx = normalize_( m_front_idx + m_capacity - 1 );
      }
  
  private:
      pointer   m_data;
      size_type m_size;
      size_type m_capacity;
      size_type m_front_idx;
      Popper    m_popper;
  };
  
  // swap:
  
  template< class T, class Popper >
  inline void swap( ring_span<T,Popper> & lhs, ring_span<T,Popper> & rhs ) nsrs_noexcept_op( nsrs_noexcept_op( lhs.swap(rhs) ) )
  {
      lhs.swap(rhs);
  }
  
  namespace detail {
  
  //
  // ring iterator:
  //
  #if 0
  template< class RS, bool is_const >
  class ring_iterator : public std::iterator
  <
      std::random_access_iterator_tag
      , typename stdext::conditional<is_const, const typename RS::value_type, typename RS::value_type>::type
  >
  #endif
  
  template< class RS, bool is_const >
  class ring_iterator
  {
  public:
      typedef ring_iterator<RS, is_const> type;
  
      typedef std::ptrdiff_t difference_type;
      typedef typename RS::value_type value_type;
  
      typedef typename stdext::conditional<is_const, const value_type, value_type>::type * pointer;
      typedef typename stdext::conditional<is_const, const value_type, value_type>::type & reference;
      typedef std::random_access_iterator_tag iterator_category;
  
  #if nsrs_CPP11_OR_GREATER
      ring_iterator() = default;
  #else
      ring_iterator() : m_idx(), m_rs() {}
  #endif
  
  #if nsrs_RING_SPAN_LITE_EXTENSION
      // conversion to const iterator:
  
      operator ring_iterator<RS, true>() const nsrs_noexcept
      {
          return ring_iterator<RS, true>( m_idx, m_rs );
      }
  #endif
  
      // access content:
  
      reference operator*() const nsrs_noexcept
      {
          return m_rs->at( m_idx );
      }
  
      // advance iterator:
  
      type & operator++() nsrs_noexcept
      {
          ++m_idx; return *this;
      }
  
      type operator++( int ) nsrs_noexcept
      {
          type r(*this); ++*this; return r;
      }
  
      type & operator--() nsrs_noexcept
      {
          --m_idx; return *this;
      }
  
      type operator--( int ) nsrs_noexcept
      {
          type r(*this); --*this; return r;
      }
  
  #if defined(__clang__) || defined(__GNUC__)
  # pragma GCC diagnostic push
  # pragma GCC diagnostic ignored "-Wsign-conversion"
  #endif
  
      type & operator+=( int i ) nsrs_noexcept
      {
          m_idx += i; return *this;
      }
  
      type & operator-=( int i ) nsrs_noexcept
      {
          m_idx -= i; return *this;
      }
  
  #if defined(__clang__) || defined(__GNUC__)
  # pragma GCC diagnostic pop
  #endif
  
  #if nsrs_RING_SPAN_LITE_EXTENSION
  
      template< bool C >
      difference_type operator-( ring_iterator<RS,C> const & rhs ) const nsrs_noexcept
      {
          return static_cast<difference_type>( this->m_idx ) - static_cast<difference_type>( rhs.m_idx );
      }
  #endif
  
      // comparison:
  
      template< bool C >
      bool operator<( ring_iterator<RS,C> const & rhs ) const nsrs_noexcept
      {
          assert( this->m_rs == rhs.m_rs ); return ( this->m_idx < rhs.m_idx );
      }
  
      template< bool C >
      bool operator==( ring_iterator<RS,C> const & rhs ) const nsrs_noexcept
      {
          assert( this->m_rs == rhs.m_rs ); return ( this->m_idx == rhs.m_idx );
      }
  
      // other comparisons expressed in <, ==:
  
      template< bool C >
      inline bool operator!=( ring_iterator<RS,C> const & rhs ) const nsrs_noexcept
      {
          return ! ( *this == rhs );
      }
  
      template< bool C >
      inline bool operator<=( ring_iterator<RS,C> const & rhs ) const nsrs_noexcept
      {
          return ! ( rhs < *this );
      }
  
      template< bool C >
      inline bool operator>( ring_iterator<RS,C> const & rhs ) const nsrs_noexcept
      {
          return rhs < *this;
      }
  
      template< bool C >
      inline bool operator>=( ring_iterator<RS,C> const & rhs ) const nsrs_noexcept
      {
          return ! ( *this < rhs );
      }
  
  private:
      friend RS;  // clang: non-class friend type 'RS' is a C++11 extension [-Wc++11-extensions]
      friend class ring_iterator<RS, ! is_const>;
  
      typedef typename RS::size_type size_type;
      typedef typename stdext::conditional<is_const, const RS, RS>::type ring_type;
  
      ring_iterator( size_type idx, typename stdext::conditional<is_const, const RS, RS>::type * rs ) nsrs_noexcept
      : m_idx( idx )
      , m_rs ( rs  )
      {}
  
  private:
      size_type   m_idx;
      ring_type * m_rs;
  };
  
  // advanced iterator:
  
  template< class RS, bool C >
  inline ring_iterator<RS,C> operator+( ring_iterator<RS,C> it, int i ) nsrs_noexcept
  {
      it += i; return it;
  }
  
  template< class RS, bool C >
  inline ring_iterator<RS,C> operator-( ring_iterator<RS,C> it, int i ) nsrs_noexcept
  {
      it -= i; return it;
  }
  
  } // namespace detail
  } // namespace stdext
  
  nsrs_RESTORE_WARNINGS()
  
  #endif // stdext_RING_SPAN_LITE_HPP
  