// // Copyright (c) 2015 Arthur O'Dwyer // Copyright 2017-2019 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 NONSTD_RING_SPAN_LITE_HPP #define NONSTD_RING_SPAN_LITE_HPP #define ring_span_lite_MAJOR 0 #define ring_span_lite_MINOR 6 #define ring_span_lite_PATCH 0 #define ring_span_lite_VERSION nsrs_STRINGIFY(ring_span_lite_MAJOR) "." nsrs_STRINGIFY(ring_span_lite_MINOR) "." nsrs_STRINGIFY(ring_span_lite_PATCH) #define nsrs_STRINGIFY( x ) nsrs_STRINGIFY_( x ) #define nsrs_STRINGIFY_( x ) #x // tweak header support: #ifdef __has_include # if __has_include() # include # endif # define nsrs_HAVE_TWEAK_HEADER 1 #else # define nsrs_HAVE_TWEAK_HEADER 0 //# pragma message("any.hpp: Note: Tweak header not supported.") #endif // ring-span-lite configuration: #define nsrs_RING_SPAN_DEFAULT 0 #define nsrs_RING_SPAN_NONSTD 1 #define nsrs_RING_SPAN_STD 2 #if !defined( nsrs_CONFIG_SELECT_RING_SPAN ) # define nsrs_CONFIG_SELECT_RING_SPAN ( nsrs_HAVE_STD_RING_SPAN ? nsrs_RING_SPAN_STD : nsrs_RING_SPAN_NONSTD ) #endif #ifndef nsrs_CONFIG_STRICT_P0059 # define nsrs_CONFIG_STRICT_P0059 0 #endif #define nsrs_RING_SPAN_LITE_EXTENSION (! nsrs_CONFIG_STRICT_P0059) #ifndef nsrs_CONFIG_POPPER_EMPTY_BASE_CLASS # define nsrs_CONFIG_POPPER_EMPTY_BASE_CLASS 0 #endif #if nsrs_CONFIG_STRICT_P0059 # undef nsrs_CONFIG_POPPER_EMPTY_BASE_CLASS # define nsrs_CONFIG_POPPER_EMPTY_BASE_CLASS 0 #endif #ifndef nsrs_CONFIG_CONFIRMS_COMPILATION_ERRORS # define nsrs_CONFIG_CONFIRMS_COMPILATION_ERRORS 0 #endif // C++ language version detection (C++23 is speculative): // Note: VC14.0/1900 (VS2015) lacks too much from C++14. #ifndef nsrs_CPLUSPLUS # if defined(_MSVC_LANG ) && !defined(__clang__) # define nsrs_CPLUSPLUS (_MSC_VER == 1900 ? 201103L : _MSVC_LANG ) # else # define nsrs_CPLUSPLUS __cplusplus # endif #endif #define nsrs_CPP98_OR_GREATER ( nsrs_CPLUSPLUS >= 199711L ) #define nsrs_CPP11_OR_GREATER ( nsrs_CPLUSPLUS >= 201103L ) #define nsrs_CPP11_OR_GREATER_ ( nsrs_CPLUSPLUS >= 201103L ) #define nsrs_CPP14_OR_GREATER ( nsrs_CPLUSPLUS >= 201402L ) #define nsrs_CPP17_OR_GREATER ( nsrs_CPLUSPLUS >= 201703L ) #define nsrs_CPP20_OR_GREATER ( nsrs_CPLUSPLUS >= 202002L ) #define nsrs_CPP23_OR_GREATER ( nsrs_CPLUSPLUS >= 202300L ) // Use C++XX std::ring_span if available and requested: #define nsrs_HAVE_STD_RING_SPAN 0 //#if nsrs_CPP17_OR_GREATER && defined(__has_include ) //# if __has_include( ) //# define nsrs_HAVE_STD_RING_SPAN 1 //# else //# define nsrs_HAVE_STD_RING_SPAN 0 //# endif //#else //# define nsrs_HAVE_STD_RING_SPAN 0 //#endif #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) ) // Compiler versions: // // MSVC++ 6.0 _MSC_VER == 1200 nsrs_COMPILER_MSVC_VERSION == 60 (Visual Studio 6.0) // MSVC++ 7.0 _MSC_VER == 1300 nsrs_COMPILER_MSVC_VERSION == 70 (Visual Studio .NET 2002) // MSVC++ 7.1 _MSC_VER == 1310 nsrs_COMPILER_MSVC_VERSION == 71 (Visual Studio .NET 2003) // MSVC++ 8.0 _MSC_VER == 1400 nsrs_COMPILER_MSVC_VERSION == 80 (Visual Studio 2005) // MSVC++ 9.0 _MSC_VER == 1500 nsrs_COMPILER_MSVC_VERSION == 90 (Visual Studio 2008) // MSVC++ 10.0 _MSC_VER == 1600 nsrs_COMPILER_MSVC_VERSION == 100 (Visual Studio 2010) // MSVC++ 11.0 _MSC_VER == 1700 nsrs_COMPILER_MSVC_VERSION == 110 (Visual Studio 2012) // MSVC++ 12.0 _MSC_VER == 1800 nsrs_COMPILER_MSVC_VERSION == 120 (Visual Studio 2013) // MSVC++ 14.0 _MSC_VER == 1900 nsrs_COMPILER_MSVC_VERSION == 140 (Visual Studio 2015) // ............ _MSVC_LANG: 201402 for -std:c++14, default // MSVC++ 14.1 _MSC_VER >= 1910 nsrs_COMPILER_MSVC_VERSION == 141 (Visual Studio 2017) // ............ _MSVC_LANG: 201402 for -std:c++14, default // ............ _MSVC_LANG: 201703 for -std:c++17 // MSVC++ 14.2 _MSC_VER >= 1920 nsrs_COMPILER_MSVC_VERSION == 142 (Visual Studio 2019) #if defined(_MSC_VER ) && !defined(__clang__) # define nsrs_COMPILER_MSVC_VER (_MSC_VER ) # define nsrs_COMPILER_MSVC_VERSION (_MSC_VER / 10 - 10 * ( 5 + (_MSC_VER < 1900 ) ) ) #else # define nsrs_COMPILER_MSVC_VER 0 # 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 // half-open range [lo..hi): //#define nsrs_BETWEEN( v, lo, hi ) ( (lo) <= (v) && (v) < (hi) ) // Presence of language and library features: #ifdef _HAS_CPP0X # define nsrs_HAS_CPP0X _HAS_CPP0X #else # define nsrs_HAS_CPP0X 0 #endif // Unless defined otherwise below, consider VC14 as C++11 for ring-span-lite: #if nsrs_COMPILER_MSVC_VER >= 1900 # undef nsrs_CPP11_OR_GREATER # define nsrs_CPP11_OR_GREATER 1 #endif #define nsrs_CPP11_90 (nsrs_CPP11_OR_GREATER_ || nsrs_COMPILER_MSVC_VER >= 1500) #define nsrs_CPP11_100 (nsrs_CPP11_OR_GREATER_ || nsrs_COMPILER_MSVC_VER >= 1600) #define nsrs_CPP11_110 (nsrs_CPP11_OR_GREATER_ || nsrs_COMPILER_MSVC_VER >= 1700) #define nsrs_CPP11_120 (nsrs_CPP11_OR_GREATER_ || nsrs_COMPILER_MSVC_VER >= 1800) #define nsrs_CPP11_140 (nsrs_CPP11_OR_GREATER_ || nsrs_COMPILER_MSVC_VER >= 1900) #define nsrs_CPP14_000 (nsrs_CPP14_OR_GREATER) #define nsrs_CPP17_000 (nsrs_CPP17_OR_GREATER) #define nsrs_CPP20_000 (nsrs_CPP20_OR_GREATER) // half-open range [lo..hi): #define nsrs_BETWEEN( v, lo, hi ) ( (lo) <= (v) && (v) < (hi) ) // Presence of C++11 language features: #define nsrs_HAVE_CONSTEXPR_11 nsrs_CPP11_140 #define nsrs_HAVE_IS_DEFAULT nsrs_CPP11_140 #define nsrs_HAVE_IS_DELETE nsrs_CPP11_140 #define nsrs_HAVE_NOEXCEPT nsrs_CPP11_140 #define nsrs_HAVE_NULLPTR nsrs_CPP11_100 // Presence of C++14 language features: #define nsrs_HAVE_CONSTEXPR_14 nsrs_CPP14_000 // Presence of C++17 language features: // no tag // Presence of C++20 language features: #define nsrs_HAVE_NO_UNIQUE_ADDRESS nsrs_CPP20_000 #define nsrs_HAVE_NO_UNIQUE_ADDRESS_MSVC (nsrs_COMPILER_MSVC_VER >= 1929) // Presence of C++ library features: // no tag // 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 // 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 #if nsrs_HAVE_NO_UNIQUE_ADDRESS # define nsrs_NO_UNIQUE_ADDRESS [[no_unique_address]] #elif nsrs_HAVE_NO_UNIQUE_ADDRESS_MSVC # define nsrs_NO_UNIQUE_ADDRESS [[msvc::no_unique_address]] #else # define nsrs_NO_UNIQUE_ADDRESS /*[[no_unique_address]]*/ #endif // Method enabling #if nsrs_CPP11_OR_GREATER #define nsrs_REQUIRES_0(...) \ template< bool B = (__VA_ARGS__), typename std::enable_if::type = 0 > #define nsrs_REQUIRES_T(...) \ , typename std::enable_if< (__VA_ARGS__), int >::type = 0 #endif // includes: #include #include #include // additional includes: #if ! nsrs_CPP11_OR_GREATER # include // std::swap() until C++11 #endif namespace nonstd { namespace ring_span_lite { // type traits C++11: namespace std11 { #if nsrs_CPP11_OR_GREATER using std::move; #else template< typename T > T const & move( T const & t ) { return t; } #endif #if nsrs_CPP11_OR_GREATER using std::true_type; using std::false_type; using std::integral_constant; #else template< typename T, T v > struct integral_constant { typedef T value_type; enum { value = v }; operator value_type() const { return value; } }; typedef integral_constant true_type; typedef integral_constant false_type; #endif // nsrs_CPP11_OR_GREATER template< bool B, class T, class F > struct conditional { typedef T type; }; template< class T, class F > struct conditional { typedef F type; }; } // namespace std11 // type traits C++17: namespace std17 { template< bool V > struct bool_constant : std11::integral_constant {}; #if nsrs_CPP17_OR_GREATER using std::is_swappable; using std::is_nothrow_swappable; #elif nsrs_CPP11_OR_GREATER namespace detail { using std::swap; struct is_swappable { template< typename T, typename = decltype( swap( std::declval(), std::declval() ) ) > static std::true_type test( int ); template< typename > static std::false_type test(...); }; struct is_nothrow_swappable { // wrap noexcept(epr) in separate function as work-around for VC140 (VS2015): template< typename T > static constexpr bool test() { return noexcept( swap( std::declval(), std::declval() ) ); } template< typename T > static auto test( int ) -> std::integral_constant()>{} template< typename > static std::false_type test(...); }; } // namespace detail // is [nothow] swappable: template< typename T > struct is_swappable : decltype( detail::is_swappable::test(0) ){}; template< typename T > struct is_nothrow_swappable : decltype( detail::is_nothrow_swappable::test(0) ){}; #endif // nsrs_CPP17_OR_GREATER } // namespace std17 // // 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 std11::move( t ); } }; template< class T > struct copy_popper { typedef T return_type; #if nsrs_CPP11_OR_GREATER # if nsrs_RING_SPAN_LITE_EXTENSION copy_popper( T t ) : m_copy( std::move(t) ) {} # else copy_popper( T && t ) : m_copy( std::move(t) ) {} # endif #else // C++98, no extension copy_popper( T const & t ) : m_copy( 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; template< typename T > bool is_power_of_2( T n ) { return n > 0 && (n & (n - 1)) == 0; } } // namespace detail // // ring span: // template < class T , class Popper = default_popper #if nsrs_RING_SPAN_LITE_EXTENSION , bool CapacityIsPowerOf2 = false #endif > class ring_span #if nsrs_CONFIG_POPPER_EMPTY_BASE_CLASS : private Popper #endif { public: typedef T value_type; typedef T * pointer; typedef T & reference; typedef T const & const_reference; typedef std::size_t size_type; #if nsrs_RING_SPAN_LITE_EXTENSION typedef ring_span< T, Popper, CapacityIsPowerOf2 > type; #else typedef ring_span< T, Popper > type; #endif 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 reverse_iterator; typedef std::reverse_iterator const_reverse_iterator; #endif // construction: template< class ContiguousIterator > ring_span( ContiguousIterator begin , ContiguousIterator end , Popper popper = Popper() ) nsrs_noexcept #if nsrs_CONFIG_POPPER_EMPTY_BASE_CLASS : Popper ( std11::move( popper ) ) , m_data ( &* begin ) , m_size ( 0 ) , m_capacity ( static_cast( end - begin ) ) , m_front_idx( 0 ) #else : m_data ( &* begin ) , m_size ( 0 ) , m_capacity ( static_cast( end - begin ) ) , m_front_idx( 0 ) , m_popper ( std11::move( popper ) ) #endif { #if nsrs_RING_SPAN_LITE_EXTENSION assert( !CapacityIsPowerOf2 || detail::is_power_of_2( m_capacity ) ); #endif } template< class ContiguousIterator > ring_span( ContiguousIterator begin , ContiguousIterator end , ContiguousIterator first , size_type size , Popper popper = Popper() ) nsrs_noexcept #if nsrs_CONFIG_POPPER_EMPTY_BASE_CLASS : Popper ( std11::move( popper ) ) , m_data ( &* begin ) , m_size ( size ) , m_capacity ( static_cast( end - begin ) ) , m_front_idx( static_cast( first - begin ) ) #else : m_data ( &* begin ) , m_size ( size ) , m_capacity ( static_cast( end - begin ) ) , m_front_idx( static_cast( first - begin ) ) , m_popper ( std11::move( popper ) ) #endif { assert( m_size <= m_capacity ); #if nsrs_RING_SPAN_LITE_EXTENSION assert( !CapacityIsPowerOf2 || detail::is_power_of_2( m_capacity ) ); #endif } #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: #if nsrs_RING_SPAN_LITE_EXTENSION reference operator[]( size_type idx ) nsrs_noexcept { assert( idx < m_size ); return at_(idx); } const_reference operator[]( size_type idx ) const nsrs_noexcept { assert( idx < m_size ); return at_(idx); } #endif 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_(); #if nsrs_CONFIG_POPPER_EMPTY_BASE_CLASS return this->operator()( element ); #else return m_popper( element ); #endif } #if nsrs_RING_SPAN_LITE_EXTENSION typename Popper::return_type pop_back() { assert( ! empty() ); reference element = back_(); decrement_back_(); #if nsrs_CONFIG_POPPER_EMPTY_BASE_CLASS return this->operator()( element ); #else return m_popper( element ); #endif } #endif #if nsrs_CPP11_OR_GREATER nsrs_REQUIRES_0( std::is_copy_assignable::value ) void push_back( value_type const & value) noexcept( std::is_nothrow_copy_assignable::value ) #else void push_back( value_type const & value ) #endif { if ( full() ) increment_front_and_back_(); else increment_back_(); back_() = value; } #if nsrs_CPP11_OR_GREATER nsrs_REQUIRES_0( std::is_move_assignable::value ) void push_back( value_type && value ) noexcept( std::is_nothrow_move_assignable::value ) { if ( full() ) increment_front_and_back_(); else increment_back_(); back_() = std::move( value ); } template< typename... Args nsrs_REQUIRES_T( std::is_constructible::value && std::is_move_assignable::value ) > void emplace_back( Args &&... args ) noexcept ( std::is_nothrow_constructible::value && std::is_nothrow_move_assignable::value ) { if ( full() ) increment_front_and_back_(); else increment_back_(); back_() = T( std::forward(args)...); } #endif #if nsrs_RING_SPAN_LITE_EXTENSION #if nsrs_CPP11_OR_GREATER nsrs_REQUIRES_0( std::is_copy_assignable::value ) void push_front( T const & value ) noexcept(( std::is_nothrow_copy_assignable::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 nsrs_REQUIRES_0( std::is_move_assignable::value ) void push_front( T && value ) noexcept(( std::is_nothrow_move_assignable::value )) { if ( full() ) decrement_front_and_back_(); else decrement_front_(); front_() = std::move(value); } template< typename... Args nsrs_REQUIRES_T( std::is_constructible::value && std::is_move_assignable::value ) > void emplace_front( Args&&... args ) noexcept ( std::is_nothrow_constructible::value && std::is_nothrow_move_assignable::value ) { if ( full() ) decrement_front_and_back_(); else decrement_front_(); front_() = T( std::forward(args)...); } #endif #endif // nsrs_RING_SPAN_LITE_EXTENSION // swap: void swap( type & rhs ) #if nsrs_CPP11_OR_GREATER noexcept( std17::is_nothrow_swappable::value ) #endif { 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 ); #if !nsrs_RING_SPAN_LITE_EXTENSION swap( m_popper , rhs.m_popper ); #endif } private: friend class detail::ring_iterator; // const_iterator; friend class detail::ring_iterator; // iterator; #if nsrs_RING_SPAN_LITE_EXTENSION size_type normalize_( size_type const idx, std11::true_type ) const nsrs_noexcept { return idx & (m_capacity - 1); } size_type normalize_( size_type const idx, std11::false_type ) const nsrs_noexcept { return idx % m_capacity; } size_type normalize_( size_type const idx ) const nsrs_noexcept { return normalize_( idx, std17::bool_constant() ); } #else size_type normalize_( size_type const idx ) const nsrs_noexcept { return idx % m_capacity; } #endif // nsrs_RING_SPAN_LITE_EXTENSION 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; #if !nsrs_CONFIG_POPPER_EMPTY_BASE_CLASS nsrs_NO_UNIQUE_ADDRESS Popper m_popper; #endif }; // swap: template< class T, class Popper > inline void swap( ring_span & lhs, ring_span & 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 std11::conditional::type > #endif template< class RS, bool is_const > class ring_iterator { friend RS; // clang: non-class friend type 'RS' is a C++11 extension [-Wc++11-extensions] public: typedef ring_iterator type; typedef std::ptrdiff_t difference_type; typedef typename RS::size_type size_type; typedef typename RS::value_type value_type; typedef typename std11::conditional::type * pointer; typedef typename std11::conditional::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() const nsrs_noexcept { return ring_iterator( m_idx, m_rs ); } #endif // access content: reference operator*() const nsrs_noexcept { return m_rs->at_( m_idx ); } // see issue #21: pointer operator->() const nsrs_noexcept { return & m_rs->at_( m_idx ); } // see issue #30: #if nsrs_RING_SPAN_LITE_EXTENSION reference operator[]( size_type idx ) nsrs_noexcept { return m_rs->at_(m_idx + idx); } const reference operator[]( size_type idx ) const nsrs_noexcept { return m_rs->at_(m_idx + idx); } #endif // 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 const & rhs ) const nsrs_noexcept { return static_cast( this->m_idx ) - static_cast( rhs.m_idx ); } #endif // comparison: template< bool C > bool operator<( ring_iterator 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 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 const & rhs ) const nsrs_noexcept { return ! ( *this == rhs ); } template< bool C > inline bool operator<=( ring_iterator const & rhs ) const nsrs_noexcept { return ! ( rhs < *this ); } template< bool C > inline bool operator>( ring_iterator const & rhs ) const nsrs_noexcept { return rhs < *this; } template< bool C > inline bool operator>=( ring_iterator const & rhs ) const nsrs_noexcept { return ! ( *this < rhs ); } private: friend class ring_iterator; typedef typename std11::conditional::type ring_type; ring_iterator( size_type idx, typename std11::conditional::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 operator+( ring_iterator it, int i ) nsrs_noexcept { it += i; return it; } template< class RS, bool C > inline ring_iterator operator+( int i, ring_iterator it ) nsrs_noexcept { it += i; return it; } template< class RS, bool C > inline ring_iterator operator-( ring_iterator it, int i ) nsrs_noexcept { it -= i; return it; } } // namespace detail } // namespace ring_span_lite using ring_span_lite::ring_span; using ring_span_lite::null_popper; using ring_span_lite::default_popper; using ring_span_lite::copy_popper; } // namespace nonstd nsrs_RESTORE_WARNINGS() #endif // NONSTD_RING_SPAN_LITE_HPP