├── .buckconfig ├── .editorconfig ├── .gitattributes ├── .github └── workflows │ └── ci.yml ├── .gitignore ├── .tgitconfig ├── BUCK ├── CHANGES.txt ├── CMakeLists.txt ├── LICENSE.txt ├── README.md ├── appveyor.yml ├── cmake ├── ring-span-lite-config-version.cmake.in └── ring-span-lite-config.cmake.in ├── conanfile.py ├── example ├── 01-filter.cpp ├── 02-no-exceptions.cpp ├── 03-make-ring-span-cpp98.cpp ├── 03-make-ring-span.cpp ├── 04-clear.cpp ├── BUCK └── CMakeLists.txt ├── include └── nonstd │ ├── ring.hpp │ └── ring_span.hpp ├── project └── CodeBlocks │ ├── ring-span-lite.cbp │ └── ring-span-lite.workspace ├── script ├── create-cov-rpt.py ├── create-vcpkg.py ├── update-version.py └── upload-conan.py └── test ├── BUCK ├── CMakeLists.txt ├── lest └── lest_cpp03.hpp ├── nonstd └── ring_span.tweak.hpp ├── ring-span-main.t.cpp ├── ring-span-main.t.hpp ├── ring-span-sg14.t.hpp ├── ring-span.t.cpp ├── t-sg14.bat ├── t.bat ├── tc-cl.bat ├── tc.bat ├── tg-all.bat ├── tg-sg14.bat └── tg.bat /.buckconfig: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/martinmoene/ring-span-lite/5c2ecaa686957281dea072c545ba90e0287fba24/.buckconfig -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # Configuration file for EditorConfig, see https://EditorConfig.org 2 | 3 | # Ignore any other files further up in the file system 4 | root = true 5 | 6 | # All files: 7 | [*] 8 | # Let git determine line ending: end_of_line = lf 9 | charset = utf-8 10 | indent_size = 4 11 | indent_style = space 12 | insert_final_newline = true 13 | trim_trailing_whitespace = true 14 | 15 | # Markdown files: keep trailing space-pair as line-break 16 | [*.md] 17 | trim_trailing_whitespace = false 18 | 19 | # Python scripts: 20 | [*.py] 21 | 22 | # YAML scripts: 23 | [*.yml] 24 | indent_size = 2 25 | 26 | # Makefiles: Tab indentation (no size specified) 27 | [Makefile] 28 | indent_style = tab 29 | 30 | # C, C++ source files: 31 | [*.{h,hpp,c,cpp}] 32 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for CodeBlocks 5 | *.cbp text eol=lf 6 | *.workspace text eol=lf 7 | 8 | # Custom for Visual Studio 9 | *.cs diff=csharp 10 | *.sln merge=union 11 | *.csproj merge=union 12 | *.vbproj merge=union 13 | *.fsproj merge=union 14 | *.dbproj merge=union 15 | 16 | # Standard to msysgit 17 | *.doc diff=astextplain 18 | *.DOC diff=astextplain 19 | *.docx diff=astextplain 20 | *.DOCX diff=astextplain 21 | *.dot diff=astextplain 22 | *.DOT diff=astextplain 23 | *.pdf diff=astextplain 24 | *.PDF diff=astextplain 25 | *.rtf diff=astextplain 26 | *.RTF diff=astextplain 27 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | env: 4 | PROJECT: RING_SPAN_LITE 5 | 6 | on: 7 | push: 8 | branches: [ master ] 9 | 10 | pull_request: 11 | branches: [ master ] 12 | 13 | workflow_dispatch: 14 | 15 | jobs: 16 | gcc: 17 | strategy: 18 | fail-fast: false 19 | matrix: 20 | version: [9, 10, 11] 21 | 22 | runs-on: ubuntu-latest 23 | 24 | steps: 25 | - uses: actions/checkout@v4 26 | 27 | - name: Install GCC ${{ matrix.version }} 28 | run: sudo apt-get install -y gcc-${{ matrix.version }} g++-${{ matrix.version }} 29 | 30 | - name: Configure tests 31 | env: 32 | CXX: g++-${{ matrix.version }} 33 | run: cmake -S . -B build 34 | -D CMAKE_BUILD_TYPE:STRING=Release 35 | -D ${{ env.PROJECT }}_OPT_SELECT_NONSTD=ON 36 | -D ${{ env.PROJECT }}_OPT_BUILD_TESTS=ON 37 | -D ${{ env.PROJECT }}_OPT_BUILD_EXAMPLES=OFF 38 | 39 | - name: Build tests 40 | run: cmake --build build -j 4 41 | 42 | - name: Run tests 43 | working-directory: build 44 | run: ctest --output-on-failure -j 4 45 | 46 | clang: 47 | strategy: 48 | fail-fast: false 49 | matrix: 50 | include: 51 | - version: 11 52 | os: 'ubuntu-22.04' 53 | - version: 12 54 | os: 'ubuntu-22.04' 55 | - version: 19 56 | os: 'ubuntu-24.04' 57 | 58 | runs-on: ${{ matrix.os }} 59 | 60 | steps: 61 | - uses: actions/checkout@v4 62 | 63 | - name: Install Clang ${{ matrix.version }} 64 | run: sudo apt-get install -y clang-${{ matrix.version }} 65 | 66 | - name: Configure tests 67 | env: 68 | CXX: clang-${{ matrix.version }} 69 | run: cmake -S . -B build 70 | -D CMAKE_CXX_COMPILER=clang++-${{ matrix.version }} 71 | -D CMAKE_BUILD_TYPE:STRING=Release 72 | -D ${{ env.PROJECT }}_OPT_SELECT_NONSTD=ON 73 | -D ${{ env.PROJECT }}_OPT_BUILD_TESTS=ON 74 | -D ${{ env.PROJECT }}_OPT_BUILD_EXAMPLES=OFF 75 | 76 | - name: Build tests 77 | run: cmake --build build -j 4 78 | 79 | - name: Run tests 80 | working-directory: build 81 | run: ctest --output-on-failure -j 4 82 | 83 | msvc: 84 | strategy: 85 | fail-fast: false 86 | matrix: 87 | os: [windows-2019, windows-2022] 88 | 89 | runs-on: ${{ matrix.os }} 90 | 91 | steps: 92 | - uses: actions/checkout@v4 93 | 94 | - name: Configure tests 95 | run: cmake -S . -B build 96 | -D ${{ env.PROJECT }}_OPT_SELECT_NONSTD=ON 97 | -D ${{ env.PROJECT }}_OPT_BUILD_TESTS=ON 98 | -D ${{ env.PROJECT }}_OPT_BUILD_EXAMPLES=OFF 99 | 100 | - name: Build tests 101 | run: cmake --build build --config Release -j 4 102 | 103 | - name: Run tests 104 | working-directory: build 105 | run: ctest -C Release --output-on-failure -j 4 106 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | *.obj 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Compiled Dynamic libraries 12 | *.so 13 | *.dylib 14 | *.dll 15 | 16 | # Fortran module files 17 | *.mod 18 | 19 | # Compiled Static libraries 20 | *.lai 21 | *.la 22 | *.a 23 | *.lib 24 | 25 | # Executables 26 | *.exe 27 | *.out 28 | *.app 29 | 30 | # Buck 31 | /buck-out/ 32 | /.buckd/ 33 | /buckaroo/ 34 | .buckconfig.local 35 | BUCKAROO_DEPS 36 | 37 | # Build folder 38 | /build/ 39 | 40 | # CodeBlocks IDE files 41 | *.layout 42 | 43 | # Visual Studio Code 44 | /.vscode/ 45 | 46 | # Visual Studio 47 | /.vs/ 48 | -------------------------------------------------------------------------------- /.tgitconfig: -------------------------------------------------------------------------------- 1 | [bugtraq] 2 | url = https://github.com/martinmoene/ring-span-lite/issues/%BUGID% 3 | number = true 4 | logregex = "(\\s*(,|and)?\\s*#\\d+)+\n(\\d+)" 5 | -------------------------------------------------------------------------------- /BUCK: -------------------------------------------------------------------------------- 1 | prebuilt_cxx_library( 2 | name = 'ring-span-lite', 3 | header_only = True, 4 | header_namespace = '', 5 | exported_headers = subdir_glob([ 6 | ('include/nonstd', '**/*.hpp'), 7 | ]), 8 | visibility = [ 9 | 'PUBLIC', 10 | ], 11 | ) 12 | -------------------------------------------------------------------------------- /CHANGES.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/martinmoene/ring-span-lite/5c2ecaa686957281dea072c545ba90e0287fba24/CHANGES.txt -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2017-2018 Martin Moene 2 | # 3 | # https://github.com/martinmoene/ring-span-lite 4 | # 5 | # Distributed under the Boost Software License, Version 1.0. 6 | # (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | 8 | cmake_minimum_required( VERSION 3.8 FATAL_ERROR ) 9 | 10 | # ring_span-lite project and version, updated by script/update-version.py: 11 | 12 | project( 13 | ring_span_lite 14 | VERSION 0.7.0 15 | # DESCRIPTION "A C++yy-like ring_span type for C++98, C++11 and later in a single-file header-only library" 16 | # HOMEPAGE_URL "https://github.com/martinmoene/ring-span-lite" 17 | LANGUAGES CXX ) 18 | 19 | # Package information: 20 | 21 | set( unit_name "ring-span" ) 22 | set( package_nspace "nonstd" ) 23 | set( package_name "${unit_name}-lite" ) 24 | set( package_version "${${PROJECT_NAME}_VERSION}" ) 25 | 26 | message( STATUS "Project '${PROJECT_NAME}', package '${package_name}' version: '${package_version}'") 27 | 28 | # Toplevel or subproject: 29 | 30 | if ( CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME ) 31 | set( ring_span_IS_TOPLEVEL_PROJECT TRUE ) 32 | else() 33 | set( ring_span_IS_TOPLEVEL_PROJECT FALSE ) 34 | endif() 35 | 36 | # If toplevel project, enable building and performing of tests, disable building of examples: 37 | 38 | option( RING_SPAN_LITE_OPT_BUILD_TESTS "Build and perform ring-span-lite tests" ${ring_span_IS_TOPLEVEL_PROJECT} ) 39 | option( RING_SPAN_LITE_OPT_BUILD_EXAMPLES "Build ring-span-lite examples" OFF ) 40 | 41 | option( RING_SPAN_LITE_OPT_SELECT_STD "Select std::ring_span" OFF ) 42 | option( RING_SPAN_LITE_OPT_SELECT_NONSTD "Select nonstd::ring_span" OFF ) 43 | 44 | # If requested, build and perform tests, build examples: 45 | 46 | if ( RING_SPAN_LITE_OPT_BUILD_TESTS ) 47 | enable_testing() 48 | add_subdirectory( test ) 49 | endif() 50 | 51 | if ( RING_SPAN_LITE_OPT_BUILD_EXAMPLES ) 52 | add_subdirectory( example ) 53 | endif() 54 | 55 | # 56 | # Interface, installation and packaging 57 | # 58 | 59 | # CMake helpers: 60 | 61 | include( GNUInstallDirs ) 62 | include( CMakePackageConfigHelpers ) 63 | 64 | # Interface library: 65 | 66 | add_library( 67 | ${package_name} INTERFACE ) 68 | 69 | add_library( 70 | ${package_nspace}::${package_name} ALIAS ${package_name} ) 71 | 72 | target_include_directories( 73 | ${package_name} 74 | INTERFACE 75 | "$" 76 | "$" ) 77 | 78 | # Package configuration: 79 | # Note: package_name and package_target are used in package_config_in 80 | 81 | set( package_folder "${package_name}" ) 82 | set( package_target "${package_name}-targets" ) 83 | set( package_config "${package_name}-config.cmake" ) 84 | set( package_config_in "${package_name}-config.cmake.in" ) 85 | set( package_config_version "${package_name}-config-version.cmake" ) 86 | 87 | configure_package_config_file( 88 | "${CMAKE_CURRENT_SOURCE_DIR}/cmake/${package_config_in}" 89 | "${CMAKE_CURRENT_BINARY_DIR}/${package_config}" 90 | INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${package_folder}" 91 | ) 92 | 93 | configure_file( 94 | "${CMAKE_CURRENT_SOURCE_DIR}/cmake/${package_config_version}.in" 95 | "${CMAKE_CURRENT_BINARY_DIR}/${package_config_version}" @ONLY 96 | ) 97 | 98 | # Installation: 99 | 100 | install( 101 | TARGETS ${package_name} 102 | EXPORT ${package_target} 103 | # INCLUDES DESTINATION "${...}" # already set via target_include_directories() 104 | ) 105 | 106 | install( 107 | EXPORT ${package_target} 108 | NAMESPACE ${package_nspace}:: 109 | DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${package_folder}" 110 | ) 111 | 112 | install( 113 | FILES "${CMAKE_CURRENT_BINARY_DIR}/${package_config}" 114 | "${CMAKE_CURRENT_BINARY_DIR}/${package_config_version}" 115 | DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${package_folder}" 116 | ) 117 | 118 | install( 119 | DIRECTORY "include/" 120 | DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" 121 | ) 122 | 123 | export( 124 | EXPORT ${package_target} 125 | NAMESPACE ${package_nspace}:: 126 | FILE "${CMAKE_CURRENT_BINARY_DIR}/${package_name}-targets.cmake" 127 | ) 128 | 129 | # end of file 130 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Boost Software License - Version 1.0 - August 17th, 2003 2 | 3 | Permission is hereby granted, free of charge, to any person or organization 4 | obtaining a copy of the software and accompanying documentation covered by 5 | this license (the "Software") to use, reproduce, display, distribute, 6 | execute, and transmit the Software, and to prepare derivative works of the 7 | Software, and to permit third-parties to whom the Software is furnished to 8 | do so, all subject to the following: 9 | 10 | The copyright notices in the Software and this entire statement, including 11 | the above license grant, this restriction and the following disclaimer, 12 | must be included in all copies of the Software, in whole or in part, and 13 | all derivative works of the Software, unless such copies or derivative 14 | works are solely in the form of machine-executable object code generated by 15 | a source language processor. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 20 | SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 21 | FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 22 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | DEALINGS IN THE SOFTWARE. 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ring-span lite: A circular buffer view for C++98 and later 2 | 3 | [![Language](https://img.shields.io/badge/C%2B%2B-98/11/14/17-blue.svg)](https://en.wikipedia.org/wiki/C%2B%2B#Standardization) [![License](https://img.shields.io/badge/license-BSL-blue.svg)](https://opensource.org/licenses/BSL-1.0) [![Build Status](https://github.com/martinmoene/ring-span-lite/actions/workflows/ci.yml/badge.svg)](https://github.com/martinmoene/ring-span-lite/actions/workflows/ci.yml) [![Version](https://badge.fury.io/gh/martinmoene%2Fring-span-lite.svg)](https://github.com/martinmoene/ring-span-lite/releases) [![download](https://img.shields.io/badge/latest-download-blue.svg)](https://raw.githubusercontent.com/martinmoene/ring-span-lite/master/include/nonstd/ring_span.hpp) [![Conan](https://img.shields.io/badge/on-conan-blue.svg)](https://conan.io/center/ring-span-lite) [![Vcpkg](https://img.shields.io/badge/on-vcpkg-blue.svg)](https://vcpkg.link/ports/ring-span-lite) [![Try it on wandbox](https://img.shields.io/badge/on-wandbox-blue.svg)](https://wandbox.org/permlink/GHo8T1PIo7TV7eoG) [![Try it on godbolt online](https://img.shields.io/badge/on-godbolt-blue.svg)](https://godbolt.org/z/7n4Byc) 4 | 5 | **Contents** 6 | 7 | - [Example usage](#example-usage) 8 | - [In a nutshell](#in-a-nutshell) 9 | - [Dependencies](#dependencies) 10 | - [Installation](#installation) 11 | - [Synopsis](#synopsis) 12 | - [Reported to work with](#reported-to-work-with) 13 | - [Building the tests](#building-the-tests) 14 | - [Other ring_span implementations](#other-ring-span-implementations) 15 | - [Notes and references](#notes-and-references) 16 | - [Appendix](#appendix) 17 | 18 | Example usage 19 | ------------- 20 | 21 | ```Cpp 22 | #include "nonstd/ring_span.hpp" 23 | #include 24 | #include 25 | 26 | template< typename T, size_t N > 27 | inline size_t dim( T (&arr)[N] ) { return N; } 28 | 29 | template< typename T, class Popper> 30 | inline std::ostream & operator<<( std::ostream & os, ::nonstd::ring_span const & rs ) 31 | { 32 | os << "[ring_span: "; std::copy( rs.begin(), rs.end(), std::ostream_iterator(os, ", ") ); return os << "]"; 33 | } 34 | 35 | int main() 36 | { 37 | double arr[] = { 2.0 , 3.0, 5.0, }; 38 | double coeff[] = { 0.25, 0.5, 0.25 }; 39 | 40 | nonstd::ring_span buffer( arr, arr + dim(arr), arr, dim(arr) ); 41 | 42 | std::cout << buffer << "\n"; 43 | 44 | // new sample: 45 | buffer.push_back( 7.0 ); 46 | 47 | std::cout << buffer << "\n"; 48 | 49 | double result = std::inner_product( buffer.begin(), buffer.end(), coeff, 0.0 ); 50 | 51 | std::cout << "filter result: " << result << "\n"; 52 | } 53 | ``` 54 | 55 | ### Compile and run 56 | 57 | ```Text 58 | prompt> g++ -std=c++98 -Wall -I../include -o 01-filter.exe 01-filter.cpp && 01-filter.exe 59 | [ring_span: 2, 3, 5, ] 60 | [ring_span: 3, 5, 7, ] 61 | filter result: 5 62 | ``` 63 | 64 | Or to run with [Buck](https://buckbuild.com/): 65 | 66 | ```Text 67 | prompt> buck run example/:01-filter 68 | ``` 69 | 70 | In a nutshell 71 | ------------- 72 | 73 | **ring-span lite** is a single-file header-only library to represent a circular buffer view on a container. The library aims to provide a [C++yy-like ring_span]() for use with C++98 and later [1][2]. Its initial code is inspired on the reference implementation by Arthur O'Dwyer [3]. It is my intention to let the interface of this `ring_span` follow the unfolding standard one. 74 | 75 | This library also includes header `` to provide a data-owning ring buffer. 76 | 77 | **Features and properties of ring-span lite** are ease of installation (single header), freedom of dependencies other than the standard library. 78 | 79 | **Limitations of ring-span lite** are ... . 80 | 81 | License 82 | ------- 83 | 84 | *ring-span lite* is distributed under the [Boost Software License](LICENSE.txt). 85 | 86 | Dependencies 87 | ------------ 88 | 89 | *ring-span lite* has no other dependencies than the [C++ standard library](http://en.cppreference.com/w/cpp/header). 90 | 91 | Installation 92 | ------------ 93 | 94 | *ring-span lite* is a single-file header-only library. Put `ring_span.hpp` in the [include](include) folder directly into the project source tree or somewhere reachable from your project. 95 | 96 | Synopsis 97 | -------- 98 | 99 | **Contents** 100 | 101 | - [Types in namespace nonstd](#types-in-namespace-nonstd) 102 | - [Interface of *ring-span lite*](#interface-of-ring-span-lite) 103 | - [Non-member functions for *ring-span lite*](#non-member-functions-for-ring-span-lite) 104 | - [Configuration macros](#configuration-macros) 105 | 106 | ### Types in namespace nonstd 107 | 108 | | Purpose |[p0059](http://wg21.link/p0059)| Type | Notes | 109 | |---------|:-----------------------------:|------|-------| 110 | | Circular buffer view |✓/–| template<
 class T
 , class Popper = default_popper<T>
 , bool `CapacityIsPowerOf2` = false
>
class **ring_span** | See Note 1 below. | 111 | | Ignore element |✓| template< class T >
class **null_popper** |   | 112 | | Return element |✓| template< class T >
class **default_popper** |   | 113 | | Return element, replace original |✓| template< class T >
class **copy_popper** |   | 114 | 115 | Note 1: `CapacityIsPowerOf2` is an extension (`nsrs_CONFIG_STRICT_P0059=0`).With `CapacityIsPowerOf2` being `true`, method `normalize_()` is optimized to use bitwise and instead of modulo division. 116 | 117 | ### Interface of *ring-span lite* 118 | 119 | #### Class `ring_span` 120 | 121 | | Kind |[p0059](http://wg21.link/p0059)| Type / Method | Note / Result | 122 | |-------|:--------------:|-----------------------------|---------------| 123 | | Various types |✓| **type** |ring_span<T, Popper\[, CapacityIsPowerOf2\]> | 124 | |   |✓| **size_type** |  | 125 | | Value types |✓| **value_type** |  | 126 | |   |✓| **pointer** |  | 127 | |   |✓| **reference** |  | 128 | |   |✓| **const_reference** |  | 129 | | Iterator types |✓| **iterator** |  | 130 | |   |✓| **const_iterator** |  | 131 | |   |– | **reverse_iterator** |  | 132 | |   |– | **const_reverse_iterator** |  | 133 | | Construction |✓| **ring_span**(
It begin, It end
, Popper popper = Popper() ) noexcept | create empty span of
distance(begin,end) capacity | 134 | |   |✓| **ring_span**(
It begin, It end
, It first, size_type size
, Popper popper = Popper() ) noexcept | create partially filled span of
distance(begin,end) capacity,
size elements | 135 | |   |✓| **ring_span**( ring_span && ) | = default (>= C++11) | 136 | |   |✓| ring_span& **operator=**( ring_span && ) | = default (>= C++11) | 137 | |   |✓| **ring_span**( ring_span const & ) | implicitly deleted (>= C++11) | 138 | |   |✓| ring_span & **operator=**( ring_span const & ); | implicitly deleted (>= C++11) | 139 | |   |– | **ring_span**( ring_span const & ) | declared private (< C++11) | 140 | |   |– | ring_span & **operator=**( ring_span const & ); | declared private (< C++11) | 141 | | Iteration |✓| **begin**() noexcept | iterator | 142 | |   |✓| **begin**() noexcept | const_iterator | 143 | |   |✓| **cbegin**() noexcept | const_iterator | 144 | |   |✓| **end**() noexcept | iterator | 145 | |   |✓| **end**() noexcept | const_iterator | 146 | |   |✓| **cend**() noexcept | const_iterator | 147 | | Reverse iter. |– | **rbegin**() noexcept | reverse_iterator | 148 | |   |– | **rbegin**() noexcept | const_reverse_iterator | 149 | |   |– | **crbegin**() noexcept | const_reverse_iterator | 150 | |   |– | **rend**() noexcept | reverse_iterator | 151 | |   |– | **rend**() noexcept | const_reverse_iterator | 152 | |   |– | **crend**() noexcept | const_reverse_iterator | 153 | | Observation |✓| **empty**() noexcept | true if empty | 154 | |   |✓| **full**() noexcept | true if full | 155 | |   |✓| **size**() noexcept | current number of elements | 156 | |   |✓| **capacity**() noexcept| maximum number of elements | 157 | | Element access |✓| **front**() noexcept | reference to element at front | 158 | |   |✓| **front**() noexcept | const_reference to element at front | 159 | |   |✓| **back**() noexcept | reference to back element at back | 160 | |   |✓| **back**() noexcept | const_reference to element at back | 161 | |   |– | **operator[]**( size_type idx ) noexcept | reference to element at specified index | 162 | |   |– | **operator[]**( size_type idx ) noexcept | const_reference to element at specified index | 163 | | Elem.extraction|✓| **pop_front**() | Popper::return_type (p0059: auto) | 164 | |   |– | **pop_back**() | Popper::return_type | 165 | | Elem.insertion|✓ | **push_back**( value_type const & value ) noexcept(…) | void; restrained (>= C++11) | 166 | |   |– | **push_back**( value_type const & value ) | void; unrestrained (< C++11) | 167 | |   |✓| **push_back**( value_type && value ) noexcept(…) | void; restrained (>= C++11) | 168 | |   |✓| **emplace_back**( Args &&... args ) noexcept(…)| void; restrained (>= C++11) | 169 | |   |– | **push_front**( value_type const & value ) noexcept(…) | void; restrained (>= C++11) | 170 | |   |– | **push_front**( value_type const & value ) | void; unrestrained (< C++11) | 171 | |   |– | **push_front**( value_type && value ) noexcept(…)| void; restrained (>= C++11) | 172 | |   |– | **emplace_front**( Args &&... args ) noexcept(…) | void; restrained (>= C++11) | 173 | | Swap |✓| **swap**( ring_span & rhs ) noexcept | void; | 174 | 175 | #### Class `ring_iterator` 176 | 177 | | Kind |[p0059](http://wg21.link/p0059)| Type / Method | Note / Result | 178 | |-------|:--------------:|------------------------------|---------------| 179 | | Various types |✓| **type** |ring_span< T, Popper > | 180 | |   |✓| **difference_type** |  | 181 | | Value types |✓| **value_type** |  | 182 | |   |✓| **pointer** |  | 183 | |   |✓| **reference** |  | 184 | | Category |✓| **iterator_category** |  | 185 | | Construction |✓| **ring_iterator**() | = default (>= C++11) | 186 | |   |– | **ring_iterator**() | (< C++11) | 187 | | Conversion |– | **operator ring_iterator<…,true>**() const noexcept| const ring_iterator | 188 | | Element access|✓| **operator\***() const noexcept |reference | 189 | | Increment |✓| **operator++**() noexcept |ring_iterator<…> & | 190 | |   |✓| **operator++**( int ) noexcept |ring_iterator<…> | 191 | | Decrement |✓| **operator--**() noexcept |ring_iterator<…> & | 192 | |   |✓| **operator--**( int ) noexcept |ring_iterator<…> | 193 | | Addition |✓| **operator+=**( int i ) noexcept |ring_iterator<…> & | 194 | |   |✓| **operator-=**( int i ) noexcept |ring_iterator<…> & | 195 | | Difference |– | **operator-**( ring_iterator<…> const & rhs ) | difference_type, Note 1 | 196 | | Comparison |✓| **operator==**( ring_iterator<…> const & rhs ) const noexcept |bool, Note 1 | 197 | |   |✓| **operator!=**( ring_iterator<…> const & rhs ) const noexcept |bool, Note 1 | 198 | |   |✓| **operator<**( ring_iterator<…> const & rhs ) const noexcept |bool, Note 1 | 199 | |   |✓| **operator<=**( ring_iterator<…> const & rhs ) const noexcept |bool, Note 1 | 200 | |   |✓| **operator>**( ring_iterator<…> const & rhs ) const noexcept |bool, Note 1 | 201 | |   |✓| **operator>=**( ring_iterator<…> const & rhs ) const noexcept |bool, Note 1 | 202 | 203 | Note 1: accepts lhs and rhs of different const-ness. 204 | 205 | ### Non-member functions for *ring-span lite* 206 | 207 | | Kind |[p0059](http://wg21.link/p0059)| Function | Note / Result | 208 | |-----------------|:-----------------------------:|----------|--------| 209 | | Swap |–/✓| **swap**( ring_span<…> & lhs, ring_span<…> & rhs ) |void | 210 | | Iterator offset |✓| **operator+**( ring_iterator<…> it, int i ) noexcept | ring_iterator<…> | 211 | |   |– | **operator+**( int i, ring_iterator<…> it ) noexcept | ring_iterator<…> | 212 | |   |✓| **operator-**( ring_iterator<…> it, int i ) noexcept | ring_iterator<…> | 213 | |   |– | **operator-**( int i, ring_iterator<…> it ) noexcept | ring_iterator<…> | 214 | 215 | Legenda: – not in proposal · ✓ in proposal · –/✓ not in proposal/in sg14 code 216 | 217 | #### Class `ring` 218 | 219 | | Kind | Type / Method | Note / Result | 220 | |------|---------------|---------------| 221 | | Circular buffer | template<
 class Container
 , bool `CapacityIsPowerOf2` = false
>
class **ring** | See Note 1 below. | 222 | | Various types | **size_type** |  | 223 | | Value types | **value_type** |  | 224 | |   | **reference** |  | 225 | |   | **const_reference** |  | 226 | | Iterator types | **iterator** |  | 227 | |   | **const_iterator** |  | 228 | |   | **reverse_iterator** |  | 229 | |   | **const_reverse_iterator** |  | 230 | | Construction | **ring**() | create empty ring,
C-array, `std::array` | 231 | |   | **ring**(size_type size) | create empty ring of capacity `size`,
dynamic container | 232 | | Iteration | **begin**() noexcept | iterator | 233 | |   | **begin**() noexcept | const_iterator | 234 | |   | **cbegin**() noexcept | const_iterator | 235 | |   | **end**() noexcept | iterator | 236 | |   | **end**() noexcept | const_iterator | 237 | |   | **cend**() noexcept | const_iterator | 238 | | Reverse iter. | **rbegin**() noexcept | reverse_iterator | 239 | |   | **rbegin**() noexcept | const_reverse_iterator | 240 | |   | **crbegin**() noexcept | const_reverse_iterator | 241 | |   | **rend**() noexcept | reverse_iterator | 242 | |   | **rend**() noexcept | const_reverse_iterator | 243 | |   | **crend**() noexcept | const_reverse_iterator | 244 | | Observation | **empty**() noexcept | true if empty | 245 | |   | **full**() noexcept | true if full | 246 | |   | **size**() noexcept | current number of elements | 247 | |   | **capacity**() noexcept | maximum number of elements | 248 | | Element access | **front**() noexcept | reference to element at front | 249 | |   | **front**() noexcept | const_reference to element at front | 250 | |   | **back**() noexcept | reference to back element at back | 251 | |   | **back**() noexcept | const_reference to element at back | 252 | | Element access | **front**() noexcept | reference to element at front | 253 | |   | **front**() noexcept | const_reference to element at front | 254 | |   | **back**() noexcept | reference to back element at back | 255 | |   | **back**() noexcept | const_reference to element at back | 256 | |   | **operator[]**( size_type idx ) noexcept | reference to element at specified index | 257 | |   | **operator[]**( size_type idx ) noexcept | const_reference to element at specified index | 258 | | Elem.extraction| **pop_front**() | Popper::return_type | 259 | |   | **pop_back**() | Popper::return_type | 260 | | Elem.insertion|& **push_back**( value_type const & value ) noexcept(…) | void; restrained (>= C++11) | 261 | |   | **push_back**( value_type const & value ) | void; unrestrained (< C++11) | 262 | |   | **push_back**( value_type && value ) noexcept(…) | void; restrained (>= C++11) | 263 | |   | **emplace_back**( Args &&... args ) noexcept(…)| void; restrained (>= C++11) | 264 | |   | **push_front**( value_type const & value ) noexcept(…) | void; restrained (>= C++11) | 265 | |   | **push_front**( value_type const & value ) | void; unrestrained (< C++11) | 266 | |   | **push_front**( value_type && value ) noexcept(…)| void; restrained (>= C++11) | 267 | |   | **emplace_front**( Args &&... args ) noexcept(…) | void; restrained (>= C++11) | 268 | | Swap | **swap**( ring_span & rhs ) noexcept | void; | 269 | 270 | Note 1: `CapacityIsPowerOf2` is an extension (`nsrs_CONFIG_STRICT_P0059=0`).With `CapacityIsPowerOf2` being `true`, method `normalize_()` is optimized to use bitwise and instead of modulo division. Class `default_popper` is used as popper. 271 | 272 | ### Configuration macros 273 | 274 | #### Tweak header 275 | 276 | If the compiler supports [`__has_include()`](https://en.cppreference.com/w/cpp/preprocessor/include), *ring-span lite* supports the [tweak header](https://vector-of-bool.github.io/2020/10/04/lib-configuration.html) mechanism. Provide your *tweak header* as `nonstd/ring_span.tweak.hpp` in a folder in the include-search-path. In the tweak header, provide definitions as documented below, like `#define nsrs_CPLUSPLUS 201103L`. 277 | 278 | #### Standard selection macro 279 | 280 | \-Dnsrs\_CPLUSPLUS=199711L 281 | Define this macro to override the auto-detection of the supported C++ standard, if your compiler does not set the `__cpluplus` macro correctly. 282 | 283 | #### Select `std::ring_span` or `nonstd::ring_span` 284 | 285 | At default, *ring_span lite* uses `std::ring_span` if it is available and lets you use it via namespace `nonstd`. You can however override this default and explicitly request to use `std::ring_span` or ring_span lite's `nonstd::ring_span` as `nonstd::ring_span` via the following macros. 286 | 287 | -Dnsrs\_CONFIG\_SELECT\_RING\_SPAN=nsrs_RING_SPAN_DEFAULT 288 | Define this to `nsrs_RING_SPAN_STD` to select `std::ring_span` as `nonstd::ring_span`. Define this to `nsrs_RING_SPAN_NONSTD` to select `nonstd::ring_span` as `nonstd::ring_span`. Default is undefined, which has the same effect as defining to `nsrs_RING_SPAN_DEFAULT`. 289 | 290 | #### Disable extensions 291 | 292 | \-Dnsrs\_CONFIG\_STRICT\_P0059=0 293 | Define this to 1 to omit behaviour not present in proposal [p0059](http://wg21.link/p0059). Default is undefined (same effect as 0). 294 | 295 | #### Enable popper empty base class optimization 296 | 297 | \-Dnsrs\_CONFIG\_POPPER\_EMPTY\_BASE\_CLASS=0 298 | Poppers are often stateless. To prevent they take up space C++20 attribute `[[no_unique_address]]` is used when available. Another way to prevent up taking space is to make the popper a base class of `class ring_span`. This is what occurs with macro `nsrs_CONFIG_POPPER_EMPTY_BASE_CLASS` defined to 1. This is an extension to proposal p0059. Disabling extensions via macro `nsrs_CONFIG_STRICT_P0059` also disables this extension. Default is undefined (same effect as 0). 299 | 300 | #### Enable compilation errors 301 | 302 | \-Dnsrs\_CONFIG\_CONFIRMS\_COMPILATION\_ERRORS=0 303 | Define this to 1 to include the tests with compile-time errors. Default is undefined (same effect as 0). 304 | 305 | Reported to work with 306 | --------------------- 307 | 308 | The table below mentions the compiler versions *ring-span lite* is reported to work with. 309 | 310 | OS | Compiler | Versions | 311 | ---------:|:-----------|:---------| 312 | Windows | Clang/LLVM | ? | 313 |   | GCC | 5.2.0, 6.3.0 | 314 |   | Visual C++
(Visual Studio)| 8 (2005), 10 (2010), 11 (2012),
12 (2013), 14 (2015, 2017) | 315 | GNU/Linux | Clang/LLVM | 3.5.0 | 316 |   | GCC | 4.8.4 | 317 | OS X | ? | ? | 318 | 319 | Building the tests 320 | ------------------ 321 | 322 | To build the tests you need: 323 | - [Buck](https://buckbuild.com/) or [CMake](http://cmake.org) version 2.8.7 or later to be installed and in your PATH. 324 | - A [suitable compiler](#reported-to-work-with). 325 | 326 | The [*lest* test framework](https://github.com/martinmoene/lest) is included in the [test folder](test). 327 | 328 | ### Buck 329 | 330 | To run the tests: 331 | 332 | ```Text 333 | prompt> buck run test/ 334 | ``` 335 | 336 | ### CMake 337 | 338 | The following steps assume that the [ring-span lite source code](https://github.com/martinmoene/ring-span-lite) has been cloned into a directory named `c:\ring-span-lite`. 339 | 340 | 1. Create a directory for the build outputs for a particular architecture. 341 | Here we use c:\ring-span-lite\build-win-x86-vc10. 342 | 343 | cd c:\ring-span-lite 344 | md build-win-x86-vc10 345 | cd build-win-x86-vc10 346 | 347 | 2. Configure CMake to use the compiler of your choice (run `cmake --help` for a list). 348 | 349 | cmake -G "Visual Studio 10 2010" [see 3. below] .. 350 | 351 | 3. Optional. You can control above configuration through the following options: 352 | 353 | - `-DRING_SPAN_LITE_COLOURISE_TEST=ON`: use colour for pass, fail, default off 354 | 355 | 4. Build the test suite in the Debug configuration (alternatively use Release). 356 | 357 | cmake --build . --config Debug 358 | 359 | 5. Run the test suite. 360 | 361 | ctest -V -C Debug 362 | 363 | All tests should pass, indicating your platform is supported and you are ready to use *ring-span lite*. See the table with [supported types and functions](#features). 364 | 365 | Other ring-span implementations 366 | ------------------------------- 367 | 368 | - Bjørn Reese. [Circular span](https://github.com/breese/trial.circular). 369 | - Jan Wilmans. [ring_span](https://github.com/janwilmans/ring_span), based on code by Björn Fahller. 370 | 371 | Notes and references 372 | -------------------- 373 | 374 | ### References 375 | 376 | [1] [p0059: A proposal to add a ring span to the standard library](http://wg21.link/p0059) ([latest](http://wg21.link/p0059), [r4](http://wg21.link/p0059r4), [r3](http://wg21.link/p0059r3), [r2](http://wg21.link/p0059r2), [r1](http://wg21.link/p0059r1), [r0](http://wg21.link/p0059r0)). 377 | [2] [WG21-SG14/SG14](https://github.com/WG21-SG14/SG14/). Reference implementation of [`std::ring_span`](https://github.com/WG21-SG14/SG14/blob/master/SG14/ring.h) by [Guy Davidson](https://github.com/hatcat) and [Arthur O'Dwyer](https://github.com/Quuxplusone). 378 | [3] [Arthur O'Dwyer](https://github.com/Quuxplusone). Reference implementation of [`std::ring_span`](https://github.com/Quuxplusone/ring_view). 379 | [4] Arthur O’Dwyer. [Reference types with metadata cause problems](https://quuxplusone.github.io/blog/2018/05/30/reference-types-with-metadata-cause-problems/). 30 May 2018. 380 | [5] Phillip Johnston. [Creating a Circular Buffer in C and C++](https://embeddedartistry.com/blog/2017/4/6/circular-buffers-in-cc). 17 May 2017. 381 | [6] Jan Gaspar. [Boost.Circular Buffer](http://www.boost.org/libs/circular_buffer). 382 | 383 | Appendix 384 | -------- 385 | 386 | **Contents** 387 | 388 | - [A.1 Applets](#a1) 389 | - [A.2 Compile-time information](#a2) 390 | - [A.3 Ring-span lite test specification](#a3) 391 | 392 | 393 | ### A.1 Applets 394 | 395 | Applets demonstrate a specific use case. They are available via tag `[.applet]`. 396 | 397 | ```Text 398 | > ring-span-main.t.exe -l .applet 399 | ring_span: filter[.applet] 400 | ``` 401 | 402 | 403 | ### A.2 Compile-time information 404 | 405 | The version of *ring-span lite* is available via tag `[.version]`. The following tags are available for information on the compiler and on the C++ standard library used: `[.compiler]`, `[.stdc++]`, `[.stdlanguage]` and `[.stdlibrary]`. 406 | 407 | 408 | ### A.3 Ring-span lite test specification 409 | 410 | Note: test cases that assert are tagged with `[.assert]` and only run when [.assert] is included on the command line, like: `test [.assert] partial-test-name`. 411 | 412 |
413 | click to expand 414 |

415 | 416 | ```Text 417 | ring_span: Allows to construct an empty span from an iterator pair 418 | ring_span: Allows to construct an empty span from an iterator pair - capacity is power of 2 419 | ring_span: Allows to construct a partially filled span from an iterator pair and iterator, size 420 | ring_span: Allows to construct a partially filled span from an iterator pair and iterator, size - capacity is power of 2 421 | ring_span: Disallows to copy-construct from a ring_span (compile-time) 422 | ring_span: Disallows to copy-assign from a ring_span (compile-time) 423 | ring_span: Allows to move-construct from a ring_span (C++11) 424 | ring_span: Allows to move-assign from a ring_span (C++11) 425 | ring_span: Allows to obtain the capacity of a span 426 | ring_span: Allows to obtain the number of elements in a span (size) 427 | ring_span: Allows to check for an empty span 428 | ring_span: Allows to check for a full span 429 | ring_span: Allows to observe the element at the specified index [extension] 430 | ring_span: Allows to observe the element at the front 431 | ring_span: Allows to observe the element at the back 432 | ring_span: Allows to obtain and remove the element at the front 433 | ring_span: Allows to obtain and remove the element at the back [extension] 434 | ring_span: Allows to copy-insert an element at the front [extension] 435 | ring_span: Allows to move-insert an element at the front (C++11) [extension] 436 | ring_span: Allows to emplace an element at the front (C++11) [extension] 437 | ring_span: Allows to copy-insert an element at the back 438 | ring_span: Allows to move-insert an element at the back (C++11) 439 | ring_span: Allows to emplace an element at the back (C++11) 440 | ring_span: Adding an element to an empty span makes it non-empty (front) [extension] 441 | ring_span: Adding an element to an empty span makes it non-empty (back) 442 | ring_span: Adding an element to an empty span doesn't change its capacity (front) [extension] 443 | ring_span: Adding an element to an empty span doesn't change its capacity (back) 444 | ring_span: Adding an element to a full span leaves it full (front) [extension] 445 | ring_span: Adding an element to a full span leaves it full (back) 446 | ring_span: Adding an element to a full span doesn't change its capacity (front) [extension] 447 | ring_span: Adding an element to a full span doesn't change its capacity (back) 448 | ring_span: Removing an element from a span with one element makes it empty (front) 449 | ring_span: Removing an element from a span with one element makes it empty (back) [extension] 450 | ring_span: Removing an element from a span with one element doesn't change its capacity (front) 451 | ring_span: Removing an element from a span with one element doesn't change its capacity (back) [extension] 452 | ring_span: Removing an element from a full span makes it not full (front) 453 | ring_span: Removing an element from a full span makes it not full (back) [extension] 454 | ring_span: Removing an element from a full span doesn't change its capacity (front) 455 | ring_span: Removing an element from a full span doesn't change its capacity (back) [extension] 456 | ring_span: Allows to swap spans (member) 457 | ring_span: Allows to swap spans (non-member) 458 | ring_span: Allows to appear in range-for (C++11) 459 | ring_span: Allows iteration (non-const) 460 | ring_span: Allows iteration (const) 461 | ring_span: Allows iteration (mixed const-non-const) 462 | ring_span: Allows reverse iteration (non-const) [extension] 463 | ring_span: Allows reverse iteration (const) [extension] 464 | ring_span: Allows reverse iteration (mixed const-non-const) [extension] 465 | ring_span: A span with capacity zero is both empty and full 466 | ring_span: A full span is a delay-line of capacity elements (back-front) 467 | ring_span: A full span is a delay-line of capacity elements (front-back) [extension] 468 | ring_span: A non-full span is a stack of capacity elements (back) [extension] 469 | ring_span: A non-full span is a stack of capacity elements (front) [extension] 470 | ring_span: A non-full span behaves like an harmonica (back-front) 471 | ring_span: A non-full span behaves like an harmonica (front-back) [extension] 472 | ring_iterator: Allows conversion to const ring_iterator [extension] 473 | ring_iterator: Allows to dereference iterator (operator*()) 474 | ring_iterator: Allows to dereference iterator (operator->()) 475 | ring_iterator: Allows to index from iterator (operator[](size_t)) 476 | ring_iterator: Allows to increment iterator (prefix) 477 | ring_iterator: Allows to increment iterator (postfix) 478 | ring_iterator: Allows to decrement iterator (prefix) 479 | ring_iterator: Allows to decrement iterator (postfix) 480 | ring_iterator: Allows to advance iterator (+=) [extension] 481 | ring_iterator: Allows to advance iterator (-=) [extension] 482 | ring_iterator: Allows to offset iterator (+) [extension] 483 | ring_iterator: Allows to offset iterator (-) [extension] 484 | ring_iterator: Allows to obtain difference of iterators [extension] 485 | ring_iterator: Allows to compare iterators (==) 486 | ring_iterator: Allows to compare iterators (!=) 487 | ring_iterator: Allows to compare iterators (<) 488 | ring_iterator: Allows to compare iterators (<=) 489 | ring_iterator: Allows to compare iterators (>) 490 | ring_iterator: Allows to compare iterators (>=) 491 | ring_iterator: Allows to compare iterators (mixed const-non-const) 492 | null_popper: A null popper returns void 493 | null_popper: A null popper leaves the original element unchanged 494 | default_popper: A default popper returns the element 495 | default_popper: A default popper moves the element (C++11) 496 | default_popper: A default popper leaves the original element unchanged 497 | copy_popper: A copy popper returns the element 498 | copy_popper: A copy popper replaces the original element 499 | ring: Allows to create data owning ring from container 500 | ring: Allows to create data owning ring from container - capacity is power of 2 501 | ring: Allows to create data owning ring from std::array (C++11) 502 | ring: Allows to create data owning ring from C-array 503 | tweak header: reads tweak header if supported [tweak] 504 | ``` 505 | 506 |

507 |
508 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | version: "{branch} #{build}" 2 | 3 | shallow_clone: true 4 | 5 | image: 6 | - Visual Studio 2019 7 | - Visual Studio 2017 8 | - Visual Studio 2015 9 | 10 | platform: 11 | - Win32 12 | - x64 13 | 14 | configuration: 15 | - Debug 16 | - Release 17 | 18 | environment: 19 | matrix: 20 | - generator: "Visual Studio 16 2019" 21 | - generator: "Visual Studio 15 2017" 22 | - generator: "Visual Studio 14 2015" 23 | - generator: "Visual Studio 12 2013" 24 | - generator: "Visual Studio 11 2012" 25 | - generator: "Visual Studio 10 2010" 26 | 27 | matrix: 28 | fast_finish: true 29 | exclude: 30 | - image: Visual Studio 2015 31 | generator: "Visual Studio 15 2017" 32 | - image: Visual Studio 2015 33 | generator: "Visual Studio 16 2019" 34 | - image: Visual Studio 2017 35 | generator: "Visual Studio 16 2019" 36 | - image: Visual Studio 2017 37 | generator: "Visual Studio 14 2015" 38 | - image: Visual Studio 2017 39 | generator: "Visual Studio 12 2013" 40 | - image: Visual Studio 2017 41 | generator: "Visual Studio 11 2012" 42 | - image: Visual Studio 2017 43 | generator: "Visual Studio 10 2010" 44 | - image: Visual Studio 2019 45 | generator: "Visual Studio 15 2017" 46 | - image: Visual Studio 2019 47 | generator: "Visual Studio 14 2015" 48 | - image: Visual Studio 2019 49 | generator: "Visual Studio 12 2013" 50 | - image: Visual Studio 2019 51 | generator: "Visual Studio 11 2012" 52 | - image: Visual Studio 2019 53 | generator: "Visual Studio 10 2010" 54 | 55 | before_build: 56 | - mkdir build && cd build 57 | - cmake -A %platform% -G "%generator%" -DRING_SPAN_LITE_OPT_SELECT_NONSTD=ON -DRING_SPAN_LITE_OPT_BUILD_TESTS=ON -DRING_SPAN_LITE_OPT_BUILD_EXAMPLES=OFF .. 58 | 59 | build_script: 60 | - cmake --build . --config %configuration% 61 | 62 | test_script: 63 | - ctest --output-on-failure -C %configuration% 64 | -------------------------------------------------------------------------------- /cmake/ring-span-lite-config-version.cmake.in: -------------------------------------------------------------------------------- 1 | # Adapted from write_basic_package_version_file(... COMPATIBILITY SameMajorVersion) output 2 | # ARCH_INDEPENDENT is only present in cmake 3.14 and onwards 3 | 4 | set( PACKAGE_VERSION "@package_version@" ) 5 | 6 | if( PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION ) 7 | set( PACKAGE_VERSION_COMPATIBLE FALSE ) 8 | else() 9 | if( "@package_version@" MATCHES "^([0-9]+)\\." ) 10 | set( CVF_VERSION_MAJOR "${CMAKE_MATCH_1}" ) 11 | else() 12 | set( CVF_VERSION_MAJOR "@package_version@" ) 13 | endif() 14 | 15 | if( PACKAGE_FIND_VERSION_MAJOR STREQUAL CVF_VERSION_MAJOR ) 16 | set( PACKAGE_VERSION_COMPATIBLE TRUE ) 17 | else() 18 | set( PACKAGE_VERSION_COMPATIBLE FALSE ) 19 | endif() 20 | 21 | if( PACKAGE_FIND_VERSION STREQUAL PACKAGE_VERSION ) 22 | set( PACKAGE_VERSION_EXACT TRUE ) 23 | endif() 24 | endif() 25 | -------------------------------------------------------------------------------- /cmake/ring-span-lite-config.cmake.in: -------------------------------------------------------------------------------- 1 | @PACKAGE_INIT@ 2 | 3 | # Only include targets once: 4 | 5 | if( NOT TARGET @package_nspace@::@package_name@ ) 6 | include( "${CMAKE_CURRENT_LIST_DIR}/@package_target@.cmake" ) 7 | endif() 8 | -------------------------------------------------------------------------------- /conanfile.py: -------------------------------------------------------------------------------- 1 | from conans import ConanFile, CMake 2 | 3 | class RingSpanLiteConan(ConanFile): 4 | version = "0.7.0" 5 | name = "ring-span-lite" 6 | description = "ring-span" 7 | license = "Boost Software License - Version 1.0. http://www.boost.org/LICENSE_1_0.txt" 8 | url = "https://github.com/martinmoene/ring-span-lite.git" 9 | exports_sources = "include/nonstd/*", "CMakeLists.txt", "cmake/*", "LICENSE.txt" 10 | settings = "compiler", "build_type", "arch" 11 | build_policy = "missing" 12 | author = "Martin Moene" 13 | 14 | def build(self): 15 | """Avoid warning on build step""" 16 | pass 17 | 18 | def package(self): 19 | """Run CMake install""" 20 | cmake = CMake(self) 21 | cmake.definitions["RING_SPAN_LITE_OPT_BUILD_TESTS"] = "OFF" 22 | cmake.definitions["RING_SPAN_LITE_OPT_BUILD_EXAMPLES"] = "OFF" 23 | cmake.configure() 24 | cmake.install() 25 | 26 | def package_info(self): 27 | self.info.header_only() 28 | -------------------------------------------------------------------------------- /example/01-filter.cpp: -------------------------------------------------------------------------------- 1 | #include "nonstd/ring_span.hpp" 2 | #include 3 | #include 4 | 5 | template< typename T, size_t N > 6 | inline size_t dim( T (&arr)[N] ) { return N; } 7 | 8 | template< typename T, class Popper> 9 | inline std::ostream & operator<<( std::ostream & os, ::nonstd::ring_span const & rs ) 10 | { 11 | os << "[ring_span: "; std::copy( rs.begin(), rs.end(), std::ostream_iterator(os, ", ") ); return os << "]"; 12 | } 13 | 14 | int main() 15 | { 16 | double arr[] = { 2.0 , 3.0, 5.0, }; 17 | double coeff[] = { 0.25, 0.5, 0.25 }; 18 | 19 | nonstd::ring_span buffer( arr, arr + dim(arr), arr, dim(arr) ); 20 | 21 | std::cout << buffer << "\n"; 22 | 23 | // new sample: 24 | buffer.push_back( 7.0 ); 25 | 26 | std::cout << buffer << "\n"; 27 | 28 | double result = std::inner_product( buffer.begin(), buffer.end(), coeff, 0.0 ); 29 | 30 | std::cout << "filter result: " << result << "\n"; 31 | } 32 | 33 | // g++ -std=c++98 -Wall -I../include -o 01-filter.exe 01-filter.cpp && 01-filter.exe 34 | // cl -EHsc -I../include 01-filter.cpp && 01-filter.exe 35 | -------------------------------------------------------------------------------- /example/02-no-exceptions.cpp: -------------------------------------------------------------------------------- 1 | #include "nonstd/ring_span.hpp" 2 | 3 | using nonstd::ring_span; 4 | 5 | template< typename T, size_t N > 6 | inline size_t dim( T (&arr)[N] ) { return N; } 7 | 8 | int main() 9 | { 10 | double arr[] = { 0 , 0, 0, }; 11 | 12 | ring_span spn( arr, arr + dim(arr) ); 13 | } 14 | 15 | // cl -nologo -I../include 02-no-exceptions.cpp && 02-no-exceptions 16 | // g++ -Wall -fno-exceptions -I../include -o 02-no-exceptions 02-no-exceptions.cpp && 02-no-exceptions 17 | -------------------------------------------------------------------------------- /example/03-make-ring-span-cpp98.cpp: -------------------------------------------------------------------------------- 1 | // example/04-make-ring-span-cpp98.cpp 2 | // make_ring_span() requires move semantics (C++11 or later). 3 | 4 | #include "nonstd/ring_span.hpp" 5 | 6 | namespace nonstd { 7 | 8 | // Tag to create empty ring_span: 9 | 10 | const struct make_empty_t{} make_empty; 11 | 12 | } // namespace nonstd 13 | 14 | namespace nonstd { 15 | namespace detail { 16 | 17 | template< typename T, T v > struct integral_constant{}; 18 | typedef integral_constant< bool, true > true_type; 19 | typedef integral_constant< bool, false > false_type; 20 | 21 | template < typename T > struct is_array : false_type {}; 22 | template < typename T > struct is_array< T[] > : true_type {}; 23 | template < typename T, size_t N > struct is_array< T[N] > : true_type {}; 24 | 25 | #define vtypeof( C ) \ 26 | typename nonstd::detail::vtype::type 27 | 28 | template< typename C > 29 | struct vtype 30 | { 31 | typedef typename C::value_type type; 32 | }; 33 | 34 | template< typename T > 35 | struct vtype< T* > 36 | { 37 | typedef T type; 38 | }; 39 | 40 | template< typename C > 41 | C & ident( C & c ) 42 | { 43 | return c; 44 | } 45 | 46 | template< typename T, size_t N > 47 | T* ident( T(&a)[N] ) 48 | { 49 | return a; 50 | } 51 | 52 | template< typename T, size_t N > 53 | inline T* data( T(&arr)[N] ) 54 | { 55 | return &arr[0]; 56 | } 57 | 58 | template< typename T, size_t N > 59 | inline size_t size( T(&)[N] ) 60 | { 61 | return N; 62 | } 63 | 64 | template< typename C > 65 | inline typename C::pointer 66 | data( C & cont ) 67 | { 68 | return cont.data(); 69 | } 70 | 71 | template< typename C > 72 | inline typename C::size_type 73 | size( C & cont ) 74 | { 75 | return cont.size(); 76 | } 77 | 78 | } // namespace detail 79 | 80 | } // namespace nonstd 81 | 82 | // Create filled or empty ring_buffer from container: 83 | 84 | #define nsrs_MAKE_RING_SPAN( name, cont, T ) \ 85 | nonstd::ring_span name( \ 86 | nonstd::detail::data(cont), nonstd::detail::data(cont) + nonstd::detail::size(cont), \ 87 | nonstd::detail::data(cont), nonstd::detail::size(cont) ) 88 | 89 | #define nsrs_MAKE_RING_SPAN_EMPTY( name, cont, T ) \ 90 | nonstd::ring_span name( \ 91 | nonstd::detail::data(cont), nonstd::detail::data(cont) + nonstd::detail::size(cont) ) 92 | 93 | //------------------------------------------------------------------------ 94 | // Application: 95 | 96 | #include 97 | #include 98 | #include 99 | 100 | #include 101 | #include 102 | #include 103 | 104 | template< typename T > 105 | std::ostream & operator<<( std::ostream & os, nonstd::ring_span const & spn ) 106 | { 107 | os << "{ "; 108 | std::copy( spn.cbegin(), spn.cend(), std::ostream_iterator(os, ", ") ); 109 | return os << "}"; 110 | } 111 | 112 | #define print( spn ) \ 113 | std::cout << #spn ": capacity: " << spn.capacity() << " size: " << spn.size() << ", content: " << spn << "\n"; 114 | 115 | int main() 116 | { 117 | { 118 | int arr[] = { 0, 1 , 2 }; 119 | 120 | // typedef typename nonstd::detail::vtype< int(&)[3]>::type value_type; 121 | // typedef typename nonstd::detail::vtype< std::vector >::type value_type; 122 | 123 | // int aaa[10]; 124 | // vtypeof(aaa) elem; 125 | 126 | nsrs_MAKE_RING_SPAN( spn_c_array_filled, arr, int ); 127 | nsrs_MAKE_RING_SPAN_EMPTY( spn_c_array_empty, arr, int ); 128 | 129 | print( spn_c_array_filled ); 130 | print( spn_c_array_empty ); 131 | }{ 132 | // std::array arr = {{ 0, 1 , 2, 3 }}; 133 | // 134 | // nsrs_MAKE_RING_SPAN( spn_std_array_filled, arr, int ); 135 | // nsrs_MAKE_RING_SPAN_EMPTY( spn_std_array_empty, arr, int ); 136 | // 137 | // print( spn_std_array_filled ); 138 | // print( spn_std_array_empty ); 139 | }{ 140 | // std::vector vec( 5 ); 141 | // std::iota( vec.begin(), vec.end(), 0 ); 142 | // 143 | // nsrs_MAKE_RING_SPAN( spn_std_vector_filled, vec, int ); 144 | // nsrs_MAKE_RING_SPAN_EMPTY( spn_std_vector_empty, vec, int ); 145 | // 146 | // print( spn_std_vector_filled ); 147 | // print( spn_std_vector_empty ); 148 | }{ 149 | // std::string text( "abcdef" ); 150 | // 151 | // nsrs_MAKE_RING_SPAN( spn_std_string_filled, text, int ); 152 | // nsrs_MAKE_RING_SPAN( spn_std_string_empty, text, int ); 153 | // 154 | // print( spn_std_string_filled ); 155 | // print( spn_std_string_empty ); 156 | } 157 | } 158 | 159 | // cl -nologo -W4 -EHsc -I../include 04-make-ring-span-cpp98.cpp && 04-make-ring-span-cpp98 160 | // g++ -std=c++11 -Wall -fno-exceptions -I../include -o 04-make-ring-span-cpp98 04-make-ring-span-cpp98.cpp && 04-make-ring-span-cpp98 161 | 162 | // Output: 163 | -------------------------------------------------------------------------------- /example/03-make-ring-span.cpp: -------------------------------------------------------------------------------- 1 | // example/03-make-ring-span.cpp 2 | // make_ring_span() requires move semantics (C++11 or later). 3 | 4 | #include "nonstd/ring_span.hpp" 5 | 6 | #if nsrs_CPP17_OR_GREATER 7 | # include // for std::data(), std::size() 8 | #endif 9 | 10 | #ifndef PROVIDE_MAKE_RING_SPAN_FROM_GENERIC_CONTAINER 11 | #define PROVIDE_MAKE_RING_SPAN_FROM_GENERIC_CONTAINER 0 12 | #endif 13 | 14 | namespace nonstd { 15 | 16 | // Tag to create empty ring_span: 17 | 18 | const struct make_empty_t{} make_empty; 19 | 20 | } // namespace nonstd 21 | 22 | #if PROVIDE_MAKE_RING_SPAN_FROM_GENERIC_CONTAINER 23 | 24 | namespace nonstd { 25 | namespace detail { 26 | 27 | template< typename C > 28 | inline auto vtype( C & ) -> typename C::value_type 29 | { 30 | return {}; 31 | } 32 | 33 | template< typename T, size_t N > 34 | inline auto vtype( T(&)[N] ) -> T 35 | { 36 | return {}; 37 | } 38 | 39 | #if nsrs_CPP17_OR_GREATER 40 | 41 | using std::data; 42 | using std::size; 43 | 44 | #else // nsrs_CPP17_OR_GREATER 45 | 46 | template< typename T, size_t N > 47 | inline auto data( T(&arr)[N] ) -> T* 48 | { 49 | return &arr[0]; 50 | } 51 | 52 | template< typename T, size_t N > 53 | inline auto size( T(&)[N] ) -> size_t 54 | { 55 | return N; 56 | } 57 | 58 | template< typename C > 59 | inline auto data( C & cont ) -> typename C::pointer 60 | { 61 | return cont.data(); 62 | } 63 | 64 | template< typename C > 65 | inline auto size( C & cont ) -> typename C::size_type 66 | { 67 | return cont.size(); 68 | } 69 | 70 | #endif// nsrs_CPP17_OR_GREATER 71 | 72 | } // namespace detail 73 | 74 | // Create filled or empty ring_buffer from container: 75 | 76 | template< typename C > 77 | inline auto make_ring_span( C & cont ) -> ring_span 78 | { 79 | return { detail::data(cont), detail::data(cont) + detail::size(cont), detail::data(cont), detail::size(cont) }; 80 | } 81 | 82 | template< typename C > 83 | inline auto make_ring_span( C & cont, make_empty_t ) -> ring_span 84 | { 85 | return { detail::data(cont), detail::data(cont) + detail::size(cont) }; 86 | } 87 | 88 | } // namespace nonstd 89 | 90 | #else // PROVIDE_MAKE_RING_SPAN_FROM_GENERIC_CONTAINER 91 | 92 | #if ! PROVIDE_MAKE_RING_SPAN_FROM_GENERIC_CONTAINER 93 | # include 94 | # include 95 | # include 96 | #endif 97 | 98 | namespace nonstd { 99 | 100 | // Create filled or empty ring_buffer from C-array: 101 | 102 | template< typename T, size_t N > 103 | inline auto make_ring_span( T(&arr)[N] ) -> ring_span 104 | { 105 | return { &arr[0], &arr[0] + N, &arr[0], N }; 106 | } 107 | 108 | template< typename T, size_t N > 109 | inline auto make_ring_span( T(&arr)[N], make_empty_t ) -> ring_span 110 | { 111 | return { &arr[0], &arr[0] + N }; 112 | } 113 | 114 | // Create filled or empty ring_buffer from std::array: 115 | 116 | template< typename T, size_t N > 117 | inline auto make_ring_span( std::array & arr ) -> ring_span 118 | { 119 | return { arr.data(), arr.data() + N, arr.data(), N }; 120 | } 121 | 122 | template< typename T, size_t N > 123 | inline auto make_ring_span( std::array & arr, make_empty_t ) -> ring_span 124 | { 125 | return { arr.data(), arr.data() + N }; 126 | } 127 | 128 | // Create filled or empty ring_buffer from std::vector: 129 | 130 | template< typename T > 131 | inline auto make_ring_span( std::vector & vec ) -> ring_span 132 | { 133 | return { vec.data(), vec.data() + vec.size(), vec.data(), vec.size() }; 134 | } 135 | 136 | template< typename T > 137 | inline auto make_ring_span( std::vector & vec, make_empty_t ) -> ring_span 138 | { 139 | return { vec.data(), vec.data() + vec.size() }; 140 | } 141 | 142 | // Create filled or empty ring_buffer from std::basic_string: 143 | 144 | template< typename T > 145 | inline auto make_ring_span( std::basic_string & str ) -> ring_span 146 | { 147 | return { str.data(), str.data() + str.size(), str.data(), str.size() }; 148 | } 149 | 150 | template< typename T > 151 | inline auto make_ring_span( std::basic_string & str, make_empty_t ) -> ring_span 152 | { 153 | return { str.data(), str.data() + str.size() }; 154 | } 155 | 156 | } // namespace nonstd 157 | 158 | #endif // PROVIDE_MAKE_RING_SPAN_FROM_GENERIC_CONTAINER 159 | 160 | //------------------------------------------------------------------------ 161 | // Application: 162 | 163 | #include 164 | #include 165 | #include 166 | 167 | #if PROVIDE_MAKE_RING_SPAN_FROM_GENERIC_CONTAINER 168 | # include 169 | # include 170 | # include 171 | #endif 172 | 173 | template< typename T > 174 | std::ostream & operator<<( std::ostream & os, nonstd::ring_span const & spn ) 175 | { 176 | os << "{ "; 177 | std::copy( spn.cbegin(), spn.cend(), std::ostream_iterator(os, ", ") ); 178 | return os << "}"; 179 | } 180 | 181 | #define print( spn ) \ 182 | std::cout << #spn ": capacity: " << spn.capacity() << " size: " << spn.size() << ", content: " << spn << "\n"; 183 | 184 | int main() 185 | { 186 | // using nonstd::ring_span; 187 | using nonstd::make_ring_span; 188 | 189 | { 190 | int arr[] = { 0, 1 , 2 }; 191 | 192 | auto spn_c_array_filled = make_ring_span( arr ); 193 | auto spn_c_array_empty = make_ring_span( arr, nonstd::make_empty ); 194 | 195 | print( spn_c_array_filled ); 196 | print( spn_c_array_empty ); 197 | }{ 198 | std::array arr = {{ 0, 1 , 2, 3 }}; 199 | 200 | auto spn_std_array_filled = make_ring_span( arr ); 201 | auto spn_std_array_empty = make_ring_span( arr, nonstd::make_empty ); 202 | 203 | print( spn_std_array_filled ); 204 | print( spn_std_array_empty ); 205 | }{ 206 | std::vector vec( 5 ); 207 | std::iota( vec.begin(), vec.end(), 0 ); 208 | 209 | auto spn_std_vector_filled = make_ring_span( vec ); 210 | auto spn_std_vector_empty = make_ring_span( vec, nonstd::make_empty ); 211 | 212 | print( spn_std_vector_filled ); 213 | print( spn_std_vector_empty ); 214 | }{ 215 | // std::string text( "abcdef" ); 216 | // 217 | // auto spn_std_string_filled = make_ring_span( text ); 218 | // auto spn_std_string_empty = make_ring_span( text, nonstd::make_empty ); 219 | // 220 | // print( spn_std_string_filled ); 221 | // print( spn_std_string_empty ); 222 | } 223 | } 224 | 225 | // cl -nologo -DPROVIDE_MAKE_RING_SPAN_FROM_GENERIC_CONTAINER=1 -W4 -EHsc -I../include 03-make-ring-span.cpp && 03-make-ring-span 226 | // g++ -std=c++11 -DPROVIDE_MAKE_RING_SPAN_FROM_GENERIC_CONTAINER=1 -Wall -fno-exceptions -I../include -o 03-make-ring-span 03-make-ring-span.cpp && 03-make-ring-span 227 | 228 | // Output: 229 | // spn_c_array_filled: capacity: 3 size: 3, content: { 0, 1, 2, } 230 | // spn_c_array_empty: capacity: 3 size: 0, content: { } 231 | // spn_std_array_filled: capacity: 4 size: 4, content: { 0, 1, 2, 3, } 232 | // spn_std_array_empty: capacity: 4 size: 0, content: { } 233 | // spn_std_vector_filled: capacity: 5 size: 5, content: { 0, 1, 2, 3, 4, } 234 | // spn_std_vector_empty: capacity: 5 size: 0, content: { } 235 | -------------------------------------------------------------------------------- /example/04-clear.cpp: -------------------------------------------------------------------------------- 1 | #include "nonstd/ring_span.hpp" 2 | #include 3 | #include 4 | 5 | struct Widget{}; 6 | 7 | int main() 8 | { 9 | std::vector< std::unique_ptr> v( 10 ); 10 | nonstd::ring_span< std::unique_ptr > r( v.begin(), v.end() ); 11 | 12 | r.push_back( std::make_unique() ); 13 | r.push_back( std::make_unique() ); 14 | 15 | r = nonstd::ring_span< std::unique_ptr >( v.begin(), v.end() ); 16 | } 17 | 18 | // g++ -std=c++14 -Wall -I../include -o 04-clear.exe 04-clear.cpp && 04-clear.exe 19 | // cl -EHsc -I../include 04-clear.cpp && 04-clear.exe 20 | -------------------------------------------------------------------------------- /example/BUCK: -------------------------------------------------------------------------------- 1 | cxx_binary( 2 | name = '01-filter', 3 | srcs = [ 4 | '01-filter.cpp', 5 | ], 6 | compiler_flags = [ 7 | '-std=c++11', 8 | ], 9 | deps = [ 10 | '//:ring-span-lite', 11 | ], 12 | ) 13 | -------------------------------------------------------------------------------- /example/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright 2021-2021 by Martin Moene 2 | # 3 | # https://github.com/martinmoene/ring_span-lite 4 | # 5 | # Distributed under the Boost Software License, Version 1.0. 6 | # (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | 8 | if( NOT DEFINED CMAKE_MINIMUM_REQUIRED_VERSION ) 9 | cmake_minimum_required( VERSION 3.8 FATAL_ERROR ) 10 | endif() 11 | 12 | project( example LANGUAGES CXX ) 13 | 14 | # unit_name provided by toplevel CMakeLists.txt 15 | set( PACKAGE ${unit_name}-lite ) 16 | set( PROGRAM ${unit_name}-lite ) 17 | 18 | message( STATUS "Subproject '${PROJECT_NAME}', examples '${PROGRAM}-*'") 19 | 20 | # Target default options and definitions: 21 | 22 | set( OPTIONS "" ) 23 | #set( DEFINITIONS "" ) 24 | 25 | # Sources (.cpp), normal and no-exception, and their base names: 26 | 27 | set( SOURCES 28 | 01-filter.cpp 29 | 02-no-exceptions.cpp 30 | 03-make-ring-span-cpp98.cpp 31 | 03-make-ring-span.cpp 32 | 04-clear.cpp 33 | ) 34 | 35 | set( SOURCES_NE 36 | 02-no-exceptions.cpp 37 | ) 38 | 39 | string( REPLACE ".cpp" "" BASENAMES "${SOURCES}" ) 40 | string( REPLACE ".cpp" "" BASENAMES_NE "${SOURCES_NE}" ) 41 | 42 | # Determine options: 43 | 44 | if( MSVC ) 45 | message( STATUS "Matched: MSVC") 46 | 47 | set( BASE_OPTIONS -W3 ) 48 | set( EXCEPTIONS_OPTIONS ${BASE_OPTIONS} -EHsc ) 49 | set( NO_EXCEPTIONS_OPTIONS ${BASE_OPTIONS} ) 50 | 51 | elseif( CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|AppleClang" ) 52 | message( STATUS "CompilerId: '${CMAKE_CXX_COMPILER_ID}'") 53 | 54 | set( BASE_OPTIONS -Wall -Wextra -Wconversion -Wsign-conversion -Wno-missing-braces -fno-elide-constructors ) 55 | set( EXCEPTIONS_OPTIONS ${BASE_OPTIONS} ) 56 | set( NO_EXCEPTIONS_OPTIONS -fno-exceptions ) 57 | 58 | elseif( CMAKE_CXX_COMPILER_ID MATCHES "Intel" ) 59 | # as is 60 | message( STATUS "Matched: Intel") 61 | else() 62 | # as is 63 | message( STATUS "Matched: nothing") 64 | endif() 65 | 66 | # Function to emulate ternary operation `result = b ? x : y`: 67 | 68 | macro( ternary var boolean value1 value2 ) 69 | if( ${boolean} ) 70 | set( ${var} ${value1} ) 71 | else() 72 | set( ${var} ${value2} ) 73 | endif() 74 | endmacro() 75 | 76 | # Function to create a target: 77 | 78 | function( make_target name no_exceptions ) 79 | ternary( ne no_exceptions "-ne" "" ) 80 | 81 | add_executable ( ${PROGRAM}-${name}${ne} ${name}.cpp ) 82 | target_include_directories ( ${PROGRAM}-${name}${ne} PRIVATE ../include ) 83 | target_link_libraries ( ${PROGRAM}-${name}${ne} PRIVATE ${PACKAGE} ) 84 | if ( no_exceptions ) 85 | target_compile_options ( ${PROGRAM}-${name}${ne} PRIVATE ${NO_EXCEPTIONS_OPTIONS} ) 86 | else() 87 | target_compile_options ( ${PROGRAM}-${name}${ne} PRIVATE ${EXCEPTIONS_OPTIONS} ) 88 | endif() 89 | 90 | endfunction() 91 | 92 | # Create targets: 93 | 94 | foreach( target ${BASENAMES} ) 95 | make_target( ${target} FALSE ) 96 | endforeach() 97 | 98 | foreach( target ${BASENAMES_NE} ) 99 | make_target( ${target} TRUE ) 100 | endforeach() 101 | 102 | # end of file 103 | -------------------------------------------------------------------------------- /include/nonstd/ring.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2018 Arthur O'Dwyer 3 | // Copyright 2020-2020 by Martin Moene 4 | // 5 | // https://github.com/martinmoene/ring-span-lite 6 | // 7 | // See https://quuxplusone.github.io/blog/2018/05/30/reference-types-with-metadata-cause-problems/ 8 | // 9 | // Distributed under the Boost Software License, Version 1.0. 10 | // (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 11 | 12 | #ifndef NONSTD_RING_LITE_HPP 13 | #define NONSTD_RING_LITE_HPP 14 | 15 | #include 16 | 17 | #if nsrs_CPP11_OR_GREATER 18 | # include 19 | #endif 20 | 21 | namespace nonstd { namespace ring_span_lite { 22 | 23 | namespace std11 { 24 | 25 | template< class C > 26 | typename C::iterator begin( C & c ) { return c.begin(); } 27 | 28 | template< class C > 29 | typename C::iterator end( C & c ) { return c.end(); } 30 | 31 | template< typename T, std::size_t N > 32 | T * begin( T (&array)[N] ) { return &array[0]; } 33 | 34 | template< typename T, std::size_t N > 35 | T * end( T (&array)[N] ) { return &array[N]; } 36 | 37 | } // namespace std11 38 | 39 | template< class Q > 40 | struct is_array : std11::false_type {}; 41 | 42 | template< class T > 43 | struct is_array : std11::true_type {}; 44 | 45 | template< class T, std::size_t N > 46 | struct is_array : std11::true_type {}; 47 | 48 | template< class Q > 49 | struct is_std_array_oracle : std11::false_type{}; 50 | 51 | //#if nsrs_HAVE( ARRAY ) 52 | #if nsrs_CPP11_OR_GREATER 53 | 54 | template< class T, std::size_t Extent > 55 | struct is_std_array_oracle< std::array > : std11::true_type{}; 56 | 57 | #endif 58 | 59 | template< class Q > 60 | struct is_std_array : is_std_array_oracle< Q >{}; 61 | 62 | template< typename Container > 63 | struct vt 64 | { 65 | typedef typename Container::value_type value_type; 66 | }; 67 | 68 | template< typename T, std::size_t N > 69 | struct vt< T[N] > 70 | { 71 | typedef T value_type; 72 | }; 73 | 74 | template 75 | < 76 | typename Container /*= std::vector*/ 77 | #if nsrs_RING_SPAN_LITE_EXTENSION 78 | , bool CapacityIsPowerOf2 = false 79 | #endif 80 | > 81 | class ring 82 | { 83 | public: 84 | #if nsrs_RING_SPAN_LITE_EXTENSION 85 | typedef ring_span< 86 | typename vt::value_type 87 | , default_popper::value_type> 88 | , CapacityIsPowerOf2 89 | > RingSpan; 90 | #else 91 | typedef ring_span< typename vt::value_type > RingSpan; 92 | #endif 93 | 94 | typedef typename RingSpan::value_type value_type; 95 | typedef typename RingSpan::size_type size_type; 96 | typedef typename RingSpan::reference reference; 97 | typedef typename RingSpan::const_reference const_reference; 98 | typedef typename RingSpan::iterator iterator; 99 | typedef typename RingSpan::const_iterator const_iterator; 100 | 101 | #if nsrs_RING_SPAN_LITE_EXTENSION 102 | typedef typename RingSpan::reverse_iterator reverse_iterator; 103 | typedef typename RingSpan::const_reverse_iterator const_reverse_iterator; 104 | #endif 105 | 106 | // construct from C-Array, std::array: 107 | 108 | nsrs_REQUIRES_0(( 109 | is_array::value 110 | || is_std_array::value 111 | )) 112 | explicit ring() 113 | : cont() 114 | , rs( std11::begin(cont), std11::end(cont) ) 115 | {} 116 | 117 | // construct from container not being C-Array or std::array: 118 | 119 | nsrs_REQUIRES_0(( 120 | !is_array::value 121 | && !is_std_array::value 122 | )) 123 | explicit ring( size_type capacity ) 124 | : cont( capacity ) 125 | , rs( cont.begin(), cont.end() ) 126 | {} 127 | 128 | // observers: 129 | 130 | bool empty() const nsrs_noexcept 131 | { 132 | return rs.empty(); 133 | } 134 | 135 | bool full() const nsrs_noexcept 136 | { 137 | return rs.full(); 138 | } 139 | 140 | size_type size() const nsrs_noexcept 141 | { 142 | return rs.size(); 143 | } 144 | 145 | size_type capacity() const nsrs_noexcept 146 | { 147 | return rs.capacity(); 148 | } 149 | 150 | // element access: 151 | 152 | reference front() nsrs_noexcept 153 | { 154 | return rs.front(); 155 | } 156 | 157 | const_reference front() const nsrs_noexcept 158 | { 159 | return rs.front(); 160 | } 161 | 162 | reference back() nsrs_noexcept 163 | { 164 | return rs.back(); 165 | } 166 | 167 | const_reference back() const nsrs_noexcept 168 | { 169 | return rs.back(); 170 | } 171 | 172 | // iteration: 173 | 174 | iterator begin() nsrs_noexcept 175 | { 176 | return rs.begin(); 177 | } 178 | 179 | const_iterator begin() const nsrs_noexcept 180 | { 181 | return rs.begin(); 182 | } 183 | 184 | const_iterator cbegin() const nsrs_noexcept 185 | { 186 | return rs.cbegin(); 187 | } 188 | 189 | iterator end() nsrs_noexcept 190 | { 191 | return rs.end(); 192 | } 193 | 194 | const_iterator end() const nsrs_noexcept 195 | { 196 | return rs.end(); 197 | } 198 | 199 | const_iterator cend() const nsrs_noexcept 200 | { 201 | return rs.cend(); 202 | } 203 | 204 | #if nsrs_RING_SPAN_LITE_EXTENSION 205 | 206 | reverse_iterator rbegin() nsrs_noexcept 207 | { 208 | return rs.rbegin(); 209 | } 210 | 211 | reverse_iterator rend() nsrs_noexcept 212 | { 213 | return rs.rend(); 214 | } 215 | 216 | const_reverse_iterator rbegin() const nsrs_noexcept 217 | { 218 | return rs.rbegin(); 219 | } 220 | 221 | const_reverse_iterator rend() const nsrs_noexcept 222 | { 223 | return rs.rend(); 224 | } 225 | 226 | const_reverse_iterator crbegin() const nsrs_noexcept 227 | { 228 | return rs.crbegin(); 229 | } 230 | 231 | const_reverse_iterator crend() const nsrs_noexcept 232 | { 233 | return rs.crend(); 234 | } 235 | #endif 236 | 237 | #if nsrs_RING_SPAN_LITE_EXTENSION 238 | reference operator[]( size_type idx ) nsrs_noexcept 239 | { 240 | return rs[ idx ]; 241 | } 242 | 243 | const_reference operator[]( size_type idx ) const nsrs_noexcept 244 | { 245 | return rs[ idx ]; 246 | } 247 | #endif 248 | 249 | // element insertion, extraction: 250 | 251 | value_type pop_front() 252 | { 253 | return rs.pop_front(); 254 | } 255 | 256 | #if nsrs_RING_SPAN_LITE_EXTENSION 257 | value_type pop_back() 258 | { 259 | return rs.pop_back(); 260 | } 261 | #endif 262 | 263 | #if nsrs_CPP11_OR_GREATER 264 | nsrs_REQUIRES_0( std::is_copy_assignable::value ) 265 | void push_back( value_type const & value) noexcept( std::is_nothrow_copy_assignable::value ) 266 | #else 267 | void push_back( value_type const & value ) 268 | #endif 269 | { 270 | rs.push_back( value ); 271 | } 272 | 273 | #if nsrs_CPP11_OR_GREATER 274 | nsrs_REQUIRES_0( std::is_move_assignable::value ) 275 | void push_back( value_type && value ) noexcept( std::is_nothrow_move_assignable::value ) 276 | { 277 | rs.push_back( std::move( value ) ); 278 | } 279 | 280 | template< typename... Args 281 | nsrs_REQUIRES_T( 282 | std::is_constructible::value 283 | && std::is_move_assignable::value 284 | ) 285 | > 286 | void emplace_back( Args &&... args ) noexcept 287 | ( 288 | std::is_nothrow_constructible::value 289 | && std::is_nothrow_move_assignable::value 290 | ) 291 | { 292 | rs.emplace_back( std::forward(args)... ); 293 | } 294 | #endif 295 | 296 | #if nsrs_RING_SPAN_LITE_EXTENSION 297 | 298 | #if nsrs_CPP11_OR_GREATER 299 | nsrs_REQUIRES_0( std::is_copy_assignable::value ) 300 | void push_front( value_type const & value ) noexcept(( std::is_nothrow_copy_assignable::value )) 301 | #else 302 | void push_front( value_type const & value ) 303 | #endif 304 | { 305 | rs.push_front( value ); 306 | } 307 | 308 | #if nsrs_CPP11_OR_GREATER 309 | nsrs_REQUIRES_0( std::is_move_assignable::value ) 310 | void push_front( value_type && value ) noexcept(( std::is_nothrow_move_assignable::value )) 311 | { 312 | rs.push_front( std::move( value ) ); 313 | } 314 | 315 | template< typename... Args 316 | nsrs_REQUIRES_T( 317 | std::is_constructible::value 318 | && std::is_move_assignable::value 319 | ) 320 | > 321 | void emplace_front( Args&&... args ) noexcept 322 | ( 323 | std::is_nothrow_constructible::value 324 | && std::is_nothrow_move_assignable::value 325 | ) 326 | { 327 | rs.emplace_front( std::forward(args)... ); 328 | } 329 | #endif 330 | #endif // nsrs_RING_SPAN_LITE_EXTENSION 331 | 332 | // swap: 333 | 334 | void swap( ring & rhs ) 335 | #if nsrs_CPP11_OR_GREATER 336 | noexcept( 337 | nonstd::ring_span_lite::std17::is_nothrow_swappable::value 338 | ) 339 | #endif 340 | { 341 | rhs.swap( *this ); 342 | } 343 | 344 | private: 345 | Container cont; 346 | RingSpan rs; 347 | }; 348 | 349 | } // namespace ring_span_lite 350 | 351 | // Make types available in namespace nonstd: 352 | 353 | using ring_span_lite::ring; 354 | 355 | } // namespace nonstd 356 | 357 | #endif // NONSTD_RING_LITE_HPP 358 | -------------------------------------------------------------------------------- /include/nonstd/ring_span.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2015 Arthur O'Dwyer 3 | // Copyright 2017-2019 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 7 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 | // tweak header support: 25 | 26 | #ifdef __has_include 27 | # if __has_include() 28 | # include 29 | # endif 30 | # define nsrs_HAVE_TWEAK_HEADER 1 31 | #else 32 | # define nsrs_HAVE_TWEAK_HEADER 0 33 | //# pragma message("any.hpp: Note: Tweak header not supported.") 34 | #endif 35 | 36 | // ring-span-lite configuration: 37 | 38 | #define nsrs_RING_SPAN_DEFAULT 0 39 | #define nsrs_RING_SPAN_NONSTD 1 40 | #define nsrs_RING_SPAN_STD 2 41 | 42 | #if !defined( nsrs_CONFIG_SELECT_RING_SPAN ) 43 | # define nsrs_CONFIG_SELECT_RING_SPAN ( nsrs_HAVE_STD_RING_SPAN ? nsrs_RING_SPAN_STD : nsrs_RING_SPAN_NONSTD ) 44 | #endif 45 | 46 | #ifndef nsrs_CONFIG_STRICT_P0059 47 | # define nsrs_CONFIG_STRICT_P0059 0 48 | #endif 49 | 50 | #define nsrs_RING_SPAN_LITE_EXTENSION (! nsrs_CONFIG_STRICT_P0059) 51 | 52 | #ifndef nsrs_CONFIG_POPPER_EMPTY_BASE_CLASS 53 | # define nsrs_CONFIG_POPPER_EMPTY_BASE_CLASS 0 54 | #endif 55 | 56 | #if nsrs_CONFIG_STRICT_P0059 57 | # undef nsrs_CONFIG_POPPER_EMPTY_BASE_CLASS 58 | # define nsrs_CONFIG_POPPER_EMPTY_BASE_CLASS 0 59 | #endif 60 | 61 | #ifndef nsrs_CONFIG_CONFIRMS_COMPILATION_ERRORS 62 | # define nsrs_CONFIG_CONFIRMS_COMPILATION_ERRORS 0 63 | #endif 64 | 65 | // C++ language version detection (C++23 is speculative): 66 | // Note: VC14.0/1900 (VS2015) lacks too much from C++14. 67 | 68 | #ifndef nsrs_CPLUSPLUS 69 | # if defined(_MSVC_LANG ) && !defined(__clang__) 70 | # define nsrs_CPLUSPLUS (_MSC_VER == 1900 ? 201103L : _MSVC_LANG ) 71 | # else 72 | # define nsrs_CPLUSPLUS __cplusplus 73 | # endif 74 | #endif 75 | 76 | #define nsrs_CPP98_OR_GREATER ( nsrs_CPLUSPLUS >= 199711L ) 77 | #define nsrs_CPP11_OR_GREATER ( nsrs_CPLUSPLUS >= 201103L ) 78 | #define nsrs_CPP11_OR_GREATER_ ( nsrs_CPLUSPLUS >= 201103L ) 79 | #define nsrs_CPP14_OR_GREATER ( nsrs_CPLUSPLUS >= 201402L ) 80 | #define nsrs_CPP17_OR_GREATER ( nsrs_CPLUSPLUS >= 201703L ) 81 | #define nsrs_CPP20_OR_GREATER ( nsrs_CPLUSPLUS >= 202002L ) 82 | #define nsrs_CPP23_OR_GREATER ( nsrs_CPLUSPLUS >= 202300L ) 83 | 84 | // Use C++XX std::ring_span if available and requested: 85 | 86 | #define nsrs_HAVE_STD_RING_SPAN 0 87 | 88 | //#if nsrs_CPP17_OR_GREATER && defined(__has_include ) 89 | //# if __has_include( ) 90 | //# define nsrs_HAVE_STD_RING_SPAN 1 91 | //# else 92 | //# define nsrs_HAVE_STD_RING_SPAN 0 93 | //# endif 94 | //#else 95 | //# define nsrs_HAVE_STD_RING_SPAN 0 96 | //#endif 97 | 98 | #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) ) 99 | 100 | // Compiler versions: 101 | // 102 | // MSVC++ 6.0 _MSC_VER == 1200 nsrs_COMPILER_MSVC_VERSION == 60 (Visual Studio 6.0) 103 | // MSVC++ 7.0 _MSC_VER == 1300 nsrs_COMPILER_MSVC_VERSION == 70 (Visual Studio .NET 2002) 104 | // MSVC++ 7.1 _MSC_VER == 1310 nsrs_COMPILER_MSVC_VERSION == 71 (Visual Studio .NET 2003) 105 | // MSVC++ 8.0 _MSC_VER == 1400 nsrs_COMPILER_MSVC_VERSION == 80 (Visual Studio 2005) 106 | // MSVC++ 9.0 _MSC_VER == 1500 nsrs_COMPILER_MSVC_VERSION == 90 (Visual Studio 2008) 107 | // MSVC++ 10.0 _MSC_VER == 1600 nsrs_COMPILER_MSVC_VERSION == 100 (Visual Studio 2010) 108 | // MSVC++ 11.0 _MSC_VER == 1700 nsrs_COMPILER_MSVC_VERSION == 110 (Visual Studio 2012) 109 | // MSVC++ 12.0 _MSC_VER == 1800 nsrs_COMPILER_MSVC_VERSION == 120 (Visual Studio 2013) 110 | // MSVC++ 14.0 _MSC_VER == 1900 nsrs_COMPILER_MSVC_VERSION == 140 (Visual Studio 2015) 111 | // ............ _MSVC_LANG: 201402 for -std:c++14, default 112 | // MSVC++ 14.1 _MSC_VER >= 1910 nsrs_COMPILER_MSVC_VERSION == 141 (Visual Studio 2017) 113 | // ............ _MSVC_LANG: 201402 for -std:c++14, default 114 | // ............ _MSVC_LANG: 201703 for -std:c++17 115 | // MSVC++ 14.2 _MSC_VER >= 1920 nsrs_COMPILER_MSVC_VERSION == 142 (Visual Studio 2019) 116 | 117 | #if defined(_MSC_VER ) && !defined(__clang__) 118 | # define nsrs_COMPILER_MSVC_VER (_MSC_VER ) 119 | # define nsrs_COMPILER_MSVC_VERSION (_MSC_VER / 10 - 10 * ( 5 + (_MSC_VER < 1900 ) ) ) 120 | #else 121 | # define nsrs_COMPILER_MSVC_VER 0 122 | # define nsrs_COMPILER_MSVC_VERSION 0 123 | #endif 124 | 125 | #define nsrs_COMPILER_VERSION( major, minor, patch ) ( 10 * ( 10 * (major) + (minor) ) + (patch) ) 126 | 127 | #if defined(__clang__) 128 | # define nsrs_COMPILER_CLANG_VERSION nsrs_COMPILER_VERSION( __clang_major__, __clang_minor__, __clang_patchlevel__ ) 129 | #else 130 | # define nsrs_COMPILER_CLANG_VERSION 0 131 | #endif 132 | 133 | #if defined(__GNUC__) && !defined(__clang__) 134 | # define nsrs_COMPILER_GNUC_VERSION nsrs_COMPILER_VERSION( __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__ ) 135 | #else 136 | # define nsrs_COMPILER_GNUC_VERSION 0 137 | #endif 138 | 139 | // half-open range [lo..hi): 140 | //#define nsrs_BETWEEN( v, lo, hi ) ( (lo) <= (v) && (v) < (hi) ) 141 | 142 | // Presence of language and library features: 143 | 144 | #ifdef _HAS_CPP0X 145 | # define nsrs_HAS_CPP0X _HAS_CPP0X 146 | #else 147 | # define nsrs_HAS_CPP0X 0 148 | #endif 149 | 150 | // Unless defined otherwise below, consider VC14 as C++11 for ring-span-lite: 151 | 152 | #if nsrs_COMPILER_MSVC_VER >= 1900 153 | # undef nsrs_CPP11_OR_GREATER 154 | # define nsrs_CPP11_OR_GREATER 1 155 | #endif 156 | 157 | #define nsrs_CPP11_90 (nsrs_CPP11_OR_GREATER_ || nsrs_COMPILER_MSVC_VER >= 1500) 158 | #define nsrs_CPP11_100 (nsrs_CPP11_OR_GREATER_ || nsrs_COMPILER_MSVC_VER >= 1600) 159 | #define nsrs_CPP11_110 (nsrs_CPP11_OR_GREATER_ || nsrs_COMPILER_MSVC_VER >= 1700) 160 | #define nsrs_CPP11_120 (nsrs_CPP11_OR_GREATER_ || nsrs_COMPILER_MSVC_VER >= 1800) 161 | #define nsrs_CPP11_140 (nsrs_CPP11_OR_GREATER_ || nsrs_COMPILER_MSVC_VER >= 1900) 162 | 163 | #define nsrs_CPP14_000 (nsrs_CPP14_OR_GREATER) 164 | #define nsrs_CPP17_000 (nsrs_CPP17_OR_GREATER) 165 | #define nsrs_CPP20_000 (nsrs_CPP20_OR_GREATER) 166 | 167 | // half-open range [lo..hi): 168 | #define nsrs_BETWEEN( v, lo, hi ) ( (lo) <= (v) && (v) < (hi) ) 169 | 170 | // Presence of C++11 language features: 171 | 172 | #define nsrs_HAVE_CONSTEXPR_11 nsrs_CPP11_140 173 | #define nsrs_HAVE_IS_DEFAULT nsrs_CPP11_140 174 | #define nsrs_HAVE_IS_DELETE nsrs_CPP11_140 175 | #define nsrs_HAVE_NOEXCEPT nsrs_CPP11_140 176 | #define nsrs_HAVE_NULLPTR nsrs_CPP11_100 177 | 178 | // Presence of C++14 language features: 179 | 180 | #define nsrs_HAVE_CONSTEXPR_14 nsrs_CPP14_000 181 | 182 | // Presence of C++17 language features: 183 | // no tag 184 | 185 | // Presence of C++20 language features: 186 | 187 | #define nsrs_HAVE_NO_UNIQUE_ADDRESS nsrs_CPP20_000 188 | #define nsrs_HAVE_NO_UNIQUE_ADDRESS_MSVC (nsrs_COMPILER_MSVC_VER >= 1929) 189 | 190 | // Presence of C++ library features: 191 | // no tag 192 | 193 | // Compiler warning suppression: 194 | 195 | #if defined(__clang__) 196 | # pragma clang diagnostic push 197 | # pragma clang diagnostic ignored "-Wundef" 198 | # define nsrs_RESTORE_WARNINGS() _Pragma( "clang diagnostic pop" ) 199 | 200 | #elif defined __GNUC__ 201 | # pragma GCC diagnostic push 202 | # pragma GCC diagnostic ignored "-Wundef" 203 | # define nsrs_RESTORE_WARNINGS() _Pragma( "GCC diagnostic pop" ) 204 | 205 | #elif nsrs_COMPILER_MSVC_VERSION >= 140 206 | # define nsrs_DISABLE_MSVC_WARNINGS(codes) __pragma(warning(push)) __pragma(warning(disable: codes)) 207 | # define nsrs_RESTORE_WARNINGS() __pragma(warning(pop )) 208 | 209 | // Suppress the following MSVC warnings: 210 | // - C4345: initialization behavior changed 211 | // 212 | // Suppress the following MSVC GSL warnings: 213 | // - C26439, gsl::f.6 : special function 'function' can be declared 'noexcept' 214 | // - C26440, gsl::f.6 : function 'function' can be declared 'noexcept' 215 | // - C26472, gsl::t.1 : don't use a static_cast for arithmetic conversions; 216 | // use brace initialization, gsl::narrow_cast or gsl::narrow 217 | // - C26473: gsl::t.1 : don't cast between pointer types where the source type and the target type are the same 218 | // - C26481: gsl::b.1 : don't use pointer arithmetic. Use span instead 219 | // - C26490: gsl::t.1 : don't use reinterpret_cast 220 | 221 | nsrs_DISABLE_MSVC_WARNINGS( 4345 26439 26440 26472 26473 26481 26490 ) 222 | 223 | #else 224 | # define nsrs_RESTORE_WARNINGS() /*empty*/ 225 | #endif 226 | 227 | // C++ feature usage: 228 | 229 | #if nsrs_HAVE_CONSTEXPR_11 230 | # define nsrs_constexpr constexpr 231 | #else 232 | # define nsrs_constexpr /*constexpr*/ 233 | #endif 234 | 235 | #if nsrs_HAVE_CONSTEXPR_14 236 | # define nsrs_constexpr14 constexpr 237 | #else 238 | # define nsrs_constexpr14 /*constexpr*/ 239 | #endif 240 | 241 | #if nsrs_HAVE_NOEXCEPT 242 | # define nsrs_noexcept noexcept 243 | # define nsrs_noexcept_op noexcept 244 | #else 245 | # define nsrs_noexcept /*noexcept*/ 246 | # define nsrs_noexcept_op(expr) /*noexcept(expr)*/ 247 | #endif 248 | 249 | #if nsrs_HAVE_NULLPTR 250 | # define nsrs_nullptr nullptr 251 | #else 252 | # define nsrs_nullptr NULL 253 | #endif 254 | 255 | #if nsrs_HAVE_NO_UNIQUE_ADDRESS 256 | # define nsrs_NO_UNIQUE_ADDRESS [[no_unique_address]] 257 | #elif nsrs_HAVE_NO_UNIQUE_ADDRESS_MSVC 258 | # define nsrs_NO_UNIQUE_ADDRESS [[msvc::no_unique_address]] 259 | #else 260 | # define nsrs_NO_UNIQUE_ADDRESS /*[[no_unique_address]]*/ 261 | #endif 262 | 263 | // Method enabling 264 | 265 | #if nsrs_CPP11_OR_GREATER 266 | 267 | #define nsrs_REQUIRES_0(...) \ 268 | template< bool B = (__VA_ARGS__), typename std::enable_if::type = 0 > 269 | 270 | #define nsrs_REQUIRES_T(...) \ 271 | , typename std::enable_if< (__VA_ARGS__), int >::type = 0 272 | 273 | #else 274 | 275 | #define nsrs_REQUIRES_0(...) /*empty*/ 276 | #define nsrs_REQUIRES_T(...) /*empty*/ 277 | 278 | #endif 279 | 280 | // includes: 281 | 282 | #include 283 | #include 284 | #include 285 | 286 | // additional includes: 287 | 288 | #if ! nsrs_CPP11_OR_GREATER 289 | # include // std::swap() until C++11 290 | #endif 291 | 292 | namespace nonstd { namespace ring_span_lite { 293 | 294 | // type traits C++11: 295 | 296 | namespace std11 { 297 | 298 | #if nsrs_CPP11_OR_GREATER 299 | using std::move; 300 | #else 301 | template< typename T > T const & move( T const & t ) { return t; } 302 | #endif 303 | 304 | #if nsrs_CPP11_OR_GREATER 305 | using std::true_type; 306 | using std::false_type; 307 | using std::integral_constant; 308 | #else 309 | template< typename T, T v > 310 | struct integral_constant 311 | { 312 | typedef T value_type; 313 | 314 | enum { value = v }; 315 | 316 | operator value_type() const { return value; } 317 | }; 318 | 319 | typedef integral_constant true_type; 320 | typedef integral_constant false_type; 321 | 322 | #endif // nsrs_CPP11_OR_GREATER 323 | 324 | template< bool B, class T, class F > 325 | struct conditional { typedef T type; }; 326 | 327 | template< class T, class F > 328 | struct conditional { typedef F type; }; 329 | 330 | } // namespace std11 331 | 332 | // type traits C++17: 333 | 334 | namespace std17 { 335 | 336 | template< bool V > 337 | struct bool_constant : std11::integral_constant {}; 338 | 339 | #if nsrs_CPP17_OR_GREATER 340 | 341 | using std::is_swappable; 342 | using std::is_nothrow_swappable; 343 | 344 | #elif nsrs_CPP11_OR_GREATER 345 | 346 | namespace detail { 347 | 348 | using std::swap; 349 | 350 | struct is_swappable 351 | { 352 | template< typename T, typename = decltype( swap( std::declval(), std::declval() ) ) > 353 | static std::true_type test( int ); 354 | 355 | template< typename > 356 | static std::false_type test(...); 357 | }; 358 | 359 | struct is_nothrow_swappable 360 | { 361 | // wrap noexcept(epr) in separate function as work-around for VC140 (VS2015): 362 | 363 | template< typename T > 364 | static constexpr bool test() 365 | { 366 | return noexcept( swap( std::declval(), std::declval() ) ); 367 | } 368 | 369 | template< typename T > 370 | static auto test( int ) -> std::integral_constant()>{} 371 | 372 | template< typename > 373 | static std::false_type test(...); 374 | }; 375 | 376 | } // namespace detail 377 | 378 | // is [nothow] swappable: 379 | 380 | template< typename T > 381 | struct is_swappable : decltype( detail::is_swappable::test(0) ){}; 382 | 383 | template< typename T > 384 | struct is_nothrow_swappable : decltype( detail::is_nothrow_swappable::test(0) ){}; 385 | 386 | #endif // nsrs_CPP17_OR_GREATER 387 | 388 | } // namespace std17 389 | 390 | // 391 | // element extraction policies: 392 | // 393 | 394 | template< class T > 395 | struct null_popper 396 | { 397 | typedef void return_type; 398 | 399 | void operator()( T & ) const nsrs_noexcept {} 400 | }; 401 | 402 | template< class T > 403 | struct default_popper 404 | { 405 | typedef T return_type; 406 | 407 | T operator()( T & t ) const 408 | { 409 | return std11::move( t ); 410 | } 411 | }; 412 | 413 | template< class T > 414 | struct copy_popper 415 | { 416 | typedef T return_type; 417 | 418 | #if nsrs_CPP11_OR_GREATER 419 | # if nsrs_RING_SPAN_LITE_EXTENSION 420 | copy_popper( T t ) 421 | : m_copy( std::move(t) ) 422 | {} 423 | # else 424 | copy_popper( T && t ) 425 | : m_copy( std::move(t) ) 426 | {} 427 | # endif 428 | #else // C++98, no extension 429 | copy_popper( T const & t ) 430 | : m_copy( t ) 431 | {} 432 | #endif 433 | 434 | T operator()( T & t ) const 435 | { 436 | using std::swap; 437 | T result( m_copy ); swap( t, result ); return result; 438 | } 439 | 440 | T m_copy; 441 | }; 442 | 443 | // forward-declare iterator: 444 | 445 | namespace detail { 446 | 447 | template< class, bool > 448 | class ring_iterator; 449 | 450 | template< typename T > 451 | bool is_power_of_2( T n ) 452 | { 453 | return n > 0 && (n & (n - 1)) == 0; 454 | } 455 | 456 | } // namespace detail 457 | 458 | // 459 | // ring span: 460 | // 461 | template 462 | < 463 | class T 464 | , class Popper = default_popper 465 | #if nsrs_RING_SPAN_LITE_EXTENSION 466 | , bool CapacityIsPowerOf2 = false 467 | #endif 468 | > 469 | class ring_span 470 | #if nsrs_CONFIG_POPPER_EMPTY_BASE_CLASS 471 | : private Popper 472 | #endif 473 | { 474 | public: 475 | typedef T value_type; 476 | typedef T * pointer; 477 | typedef T & reference; 478 | typedef T const & const_reference; 479 | 480 | typedef std::size_t size_type; 481 | 482 | #if nsrs_RING_SPAN_LITE_EXTENSION 483 | typedef ring_span< T, Popper, CapacityIsPowerOf2 > type; 484 | #else 485 | typedef ring_span< T, Popper > type; 486 | #endif 487 | 488 | typedef detail::ring_iterator< type, false > iterator; 489 | typedef detail::ring_iterator< type, true > const_iterator; 490 | 491 | #if nsrs_RING_SPAN_LITE_EXTENSION 492 | typedef std::reverse_iterator reverse_iterator; 493 | typedef std::reverse_iterator const_reverse_iterator; 494 | #endif 495 | 496 | // construction: 497 | 498 | template< class ContiguousIterator > 499 | ring_span( 500 | ContiguousIterator begin 501 | , ContiguousIterator end 502 | , Popper popper = Popper() 503 | ) nsrs_noexcept 504 | #if nsrs_CONFIG_POPPER_EMPTY_BASE_CLASS 505 | : Popper ( std11::move( popper ) ) 506 | , m_data ( &* begin ) 507 | , m_size ( 0 ) 508 | , m_capacity ( static_cast( end - begin ) ) 509 | , m_front_idx( 0 ) 510 | #else 511 | : m_data ( &* begin ) 512 | , m_size ( 0 ) 513 | , m_capacity ( static_cast( end - begin ) ) 514 | , m_front_idx( 0 ) 515 | , m_popper ( std11::move( popper ) ) 516 | #endif 517 | { 518 | #if nsrs_RING_SPAN_LITE_EXTENSION 519 | assert( !CapacityIsPowerOf2 || detail::is_power_of_2( m_capacity ) ); 520 | #endif 521 | } 522 | 523 | template< class ContiguousIterator > 524 | ring_span( 525 | ContiguousIterator begin 526 | , ContiguousIterator end 527 | , ContiguousIterator first 528 | , size_type size 529 | , Popper popper = Popper() 530 | ) nsrs_noexcept 531 | #if nsrs_CONFIG_POPPER_EMPTY_BASE_CLASS 532 | : Popper ( std11::move( popper ) ) 533 | , m_data ( &* begin ) 534 | , m_size ( size ) 535 | , m_capacity ( static_cast( end - begin ) ) 536 | , m_front_idx( static_cast( first - begin ) ) 537 | #else 538 | : m_data ( &* begin ) 539 | , m_size ( size ) 540 | , m_capacity ( static_cast( end - begin ) ) 541 | , m_front_idx( static_cast( first - begin ) ) 542 | , m_popper ( std11::move( popper ) ) 543 | #endif 544 | { 545 | assert( m_size <= m_capacity ); 546 | #if nsrs_RING_SPAN_LITE_EXTENSION 547 | assert( !CapacityIsPowerOf2 || detail::is_power_of_2( m_capacity ) ); 548 | #endif 549 | } 550 | 551 | #if nsrs_HAVE_IS_DEFAULT 552 | ring_span( ring_span && ) = default; 553 | ring_span& operator=( ring_span && ) = default; 554 | #else 555 | private: 556 | ring_span( ring_span const & ); 557 | ring_span & operator=( ring_span const & ); 558 | public: 559 | #endif 560 | 561 | // observers: 562 | 563 | bool empty() const nsrs_noexcept 564 | { 565 | return m_size == 0; 566 | } 567 | 568 | bool full() const nsrs_noexcept 569 | { 570 | return m_size == m_capacity; 571 | } 572 | 573 | size_type size() const nsrs_noexcept 574 | { 575 | return m_size; 576 | } 577 | 578 | size_type capacity() const nsrs_noexcept 579 | { 580 | return m_capacity; 581 | } 582 | 583 | // element access: 584 | 585 | #if nsrs_RING_SPAN_LITE_EXTENSION 586 | reference operator[]( size_type idx ) nsrs_noexcept 587 | { 588 | assert( idx < m_size ); return at_(idx); 589 | } 590 | 591 | const_reference operator[]( size_type idx ) const nsrs_noexcept 592 | { 593 | assert( idx < m_size ); return at_(idx); 594 | } 595 | #endif 596 | 597 | reference front() nsrs_noexcept 598 | { 599 | return *begin(); 600 | } 601 | 602 | const_reference front() const nsrs_noexcept 603 | { 604 | return *begin(); 605 | } 606 | 607 | reference back() nsrs_noexcept 608 | { 609 | return *(--end()); 610 | } 611 | 612 | const_reference back() const nsrs_noexcept 613 | { 614 | return *(--end()); 615 | } 616 | 617 | // iteration: 618 | 619 | iterator begin() nsrs_noexcept 620 | { 621 | return iterator( 0, this ); 622 | } 623 | 624 | const_iterator begin() const nsrs_noexcept 625 | { 626 | return cbegin(); 627 | } 628 | 629 | const_iterator cbegin() const nsrs_noexcept 630 | { 631 | return const_iterator( 0, this ); 632 | } 633 | 634 | iterator end() nsrs_noexcept 635 | { 636 | return iterator( size(), this ); 637 | } 638 | 639 | const_iterator end() const nsrs_noexcept 640 | { 641 | return cend(); 642 | } 643 | 644 | const_iterator cend() const nsrs_noexcept 645 | { 646 | return const_iterator( size(), this ); 647 | } 648 | 649 | #if nsrs_RING_SPAN_LITE_EXTENSION 650 | 651 | reverse_iterator rbegin() nsrs_noexcept 652 | { 653 | return reverse_iterator( end() ); 654 | } 655 | 656 | reverse_iterator rend() nsrs_noexcept 657 | { 658 | return reverse_iterator( begin() ); 659 | } 660 | 661 | const_reverse_iterator rbegin() const nsrs_noexcept 662 | { 663 | return crbegin(); 664 | } 665 | 666 | const_reverse_iterator rend() const nsrs_noexcept 667 | { 668 | return crend(); 669 | } 670 | 671 | const_reverse_iterator crbegin() const nsrs_noexcept 672 | { 673 | return const_reverse_iterator( cend() ); 674 | } 675 | 676 | const_reverse_iterator crend() const nsrs_noexcept 677 | { 678 | return const_reverse_iterator(cbegin()); 679 | } 680 | #endif 681 | 682 | // element insertion, extraction: 683 | 684 | typename Popper::return_type pop_front() 685 | { 686 | assert( ! empty() ); 687 | 688 | reference element = front_(); 689 | increment_front_(); 690 | 691 | #if nsrs_CONFIG_POPPER_EMPTY_BASE_CLASS 692 | return this->operator()( element ); 693 | #else 694 | return m_popper( element ); 695 | #endif 696 | } 697 | 698 | #if nsrs_RING_SPAN_LITE_EXTENSION 699 | typename Popper::return_type pop_back() 700 | { 701 | assert( ! empty() ); 702 | 703 | reference element = back_(); 704 | decrement_back_(); 705 | 706 | #if nsrs_CONFIG_POPPER_EMPTY_BASE_CLASS 707 | return this->operator()( element ); 708 | #else 709 | return m_popper( element ); 710 | #endif 711 | } 712 | #endif 713 | 714 | #if nsrs_CPP11_OR_GREATER 715 | nsrs_REQUIRES_0( std::is_copy_assignable::value ) 716 | void push_back( value_type const & value) noexcept( std::is_nothrow_copy_assignable::value ) 717 | #else 718 | void push_back( value_type const & value ) 719 | #endif 720 | { 721 | if ( full() ) increment_front_and_back_(); 722 | else increment_back_(); 723 | 724 | back_() = value; 725 | } 726 | 727 | #if nsrs_CPP11_OR_GREATER 728 | nsrs_REQUIRES_0( std::is_move_assignable::value ) 729 | void push_back( value_type && value ) noexcept( std::is_nothrow_move_assignable::value ) 730 | { 731 | if ( full() ) increment_front_and_back_(); 732 | else increment_back_(); 733 | 734 | back_() = std::move( value ); 735 | } 736 | 737 | template< typename... Args 738 | nsrs_REQUIRES_T( 739 | std::is_constructible::value 740 | && std::is_move_assignable::value 741 | ) 742 | > 743 | void emplace_back( Args &&... args ) noexcept 744 | ( 745 | std::is_nothrow_constructible::value 746 | && std::is_nothrow_move_assignable::value 747 | ) 748 | { 749 | if ( full() ) increment_front_and_back_(); 750 | else increment_back_(); 751 | 752 | back_() = T( std::forward(args)...); 753 | } 754 | #endif 755 | 756 | #if nsrs_RING_SPAN_LITE_EXTENSION 757 | 758 | #if nsrs_CPP11_OR_GREATER 759 | nsrs_REQUIRES_0( std::is_copy_assignable::value ) 760 | void push_front( T const & value ) noexcept(( std::is_nothrow_copy_assignable::value )) 761 | #else 762 | void push_front( T const & value ) 763 | #endif 764 | { 765 | if ( full() ) decrement_front_and_back_(); 766 | else decrement_front_(); 767 | 768 | front_() = value; 769 | } 770 | 771 | #if nsrs_CPP11_OR_GREATER 772 | nsrs_REQUIRES_0( std::is_move_assignable::value ) 773 | void push_front( T && value ) noexcept(( std::is_nothrow_move_assignable::value )) 774 | { 775 | if ( full() ) decrement_front_and_back_(); 776 | else decrement_front_(); 777 | 778 | front_() = std::move(value); 779 | } 780 | 781 | template< typename... Args 782 | nsrs_REQUIRES_T( 783 | std::is_constructible::value 784 | && std::is_move_assignable::value 785 | ) 786 | > 787 | void emplace_front( Args&&... args ) noexcept 788 | ( 789 | std::is_nothrow_constructible::value 790 | && std::is_nothrow_move_assignable::value 791 | ) 792 | { 793 | if ( full() ) decrement_front_and_back_(); 794 | else decrement_front_(); 795 | 796 | front_() = T( std::forward(args)...); 797 | } 798 | #endif 799 | #endif // nsrs_RING_SPAN_LITE_EXTENSION 800 | 801 | // swap: 802 | 803 | void swap( type & rhs ) 804 | #if nsrs_CPP11_OR_GREATER 805 | noexcept( 806 | std17::is_nothrow_swappable::value 807 | ) 808 | #endif 809 | { 810 | using std::swap; 811 | swap( m_data , rhs.m_data ); 812 | swap( m_size , rhs.m_size ); 813 | swap( m_capacity , rhs.m_capacity ); 814 | swap( m_front_idx, rhs.m_front_idx ); 815 | #if !nsrs_RING_SPAN_LITE_EXTENSION 816 | swap( m_popper , rhs.m_popper ); 817 | #endif 818 | } 819 | 820 | private: 821 | friend class detail::ring_iterator; // const_iterator; 822 | friend class detail::ring_iterator; // iterator; 823 | 824 | #if nsrs_RING_SPAN_LITE_EXTENSION 825 | 826 | size_type normalize_( size_type const idx, std11::true_type ) const nsrs_noexcept 827 | { 828 | return idx & (m_capacity - 1); 829 | } 830 | 831 | size_type normalize_( size_type const idx, std11::false_type ) const nsrs_noexcept 832 | { 833 | return idx % m_capacity; 834 | } 835 | 836 | size_type normalize_( size_type const idx ) const nsrs_noexcept 837 | { 838 | return normalize_( idx, std17::bool_constant() ); 839 | } 840 | #else 841 | size_type normalize_( size_type const idx ) const nsrs_noexcept 842 | { 843 | return idx % m_capacity; 844 | } 845 | #endif // nsrs_RING_SPAN_LITE_EXTENSION 846 | 847 | reference at_( size_type idx ) nsrs_noexcept 848 | { 849 | return m_data[ normalize_(m_front_idx + idx) ]; 850 | } 851 | 852 | const_reference at_( size_type idx ) const nsrs_noexcept 853 | { 854 | return m_data[ normalize_(m_front_idx + idx) ]; 855 | } 856 | 857 | reference front_() nsrs_noexcept 858 | { 859 | return *( m_data + m_front_idx ); 860 | } 861 | 862 | const_reference front_() const nsrs_noexcept 863 | { 864 | return *( m_data + m_front_idx ); 865 | } 866 | 867 | reference back_() nsrs_noexcept 868 | { 869 | return *( m_data + normalize_(m_front_idx + m_size - 1) ); 870 | } 871 | 872 | const_reference back_() const nsrs_noexcept 873 | { 874 | return *( m_data + normalize_(m_front_idx + m_size - 1) ); 875 | } 876 | 877 | void increment_front_() nsrs_noexcept 878 | { 879 | m_front_idx = normalize_(m_front_idx + 1); 880 | --m_size; 881 | } 882 | 883 | void decrement_front_() nsrs_noexcept 884 | { 885 | m_front_idx = normalize_(m_front_idx + m_capacity - 1); 886 | ++m_size; 887 | } 888 | 889 | void increment_back_() nsrs_noexcept 890 | { 891 | ++m_size; 892 | } 893 | 894 | void decrement_back_() nsrs_noexcept 895 | { 896 | --m_size; 897 | } 898 | 899 | void increment_front_and_back_() nsrs_noexcept 900 | { 901 | m_front_idx = normalize_( m_front_idx + 1 ); 902 | } 903 | 904 | void decrement_front_and_back_() nsrs_noexcept 905 | { 906 | m_front_idx = normalize_( m_front_idx + m_capacity - 1 ); 907 | } 908 | 909 | private: 910 | pointer m_data; 911 | size_type m_size; 912 | size_type m_capacity; 913 | size_type m_front_idx; 914 | #if !nsrs_CONFIG_POPPER_EMPTY_BASE_CLASS 915 | nsrs_NO_UNIQUE_ADDRESS Popper m_popper; 916 | #endif 917 | }; 918 | 919 | // swap: 920 | 921 | template< class T, class Popper > 922 | inline void swap( ring_span & lhs, ring_span & rhs ) nsrs_noexcept_op( nsrs_noexcept_op( lhs.swap(rhs) ) ) 923 | { 924 | lhs.swap(rhs); 925 | } 926 | 927 | namespace detail { 928 | 929 | // 930 | // ring iterator: 931 | // 932 | #if 0 933 | template< class RS, bool is_const > 934 | class ring_iterator : public std::iterator 935 | < 936 | std::random_access_iterator_tag 937 | , typename std11::conditional::type 938 | > 939 | #endif 940 | 941 | template< class RS, bool is_const > 942 | class ring_iterator 943 | { 944 | friend RS; // clang: non-class friend type 'RS' is a C++11 extension [-Wc++11-extensions] 945 | public: 946 | typedef ring_iterator type; 947 | 948 | typedef std::ptrdiff_t difference_type; 949 | typedef typename RS::size_type size_type; 950 | typedef typename RS::value_type value_type; 951 | 952 | typedef typename std11::conditional::type * pointer; 953 | typedef typename std11::conditional::type & reference; 954 | typedef std::random_access_iterator_tag iterator_category; 955 | 956 | #if nsrs_CPP11_OR_GREATER 957 | ring_iterator() = default; 958 | #else 959 | ring_iterator() : m_idx(), m_rs() {} 960 | #endif 961 | 962 | #if nsrs_RING_SPAN_LITE_EXTENSION 963 | // conversion to const iterator: 964 | 965 | operator ring_iterator() const nsrs_noexcept 966 | { 967 | return ring_iterator( m_idx, m_rs ); 968 | } 969 | #endif 970 | 971 | // access content: 972 | 973 | reference operator*() const nsrs_noexcept 974 | { 975 | return m_rs->at_( m_idx ); 976 | } 977 | 978 | // see issue #21: 979 | 980 | pointer operator->() const nsrs_noexcept 981 | { 982 | return & m_rs->at_( m_idx ); 983 | } 984 | 985 | // see issue #30: 986 | 987 | #if nsrs_RING_SPAN_LITE_EXTENSION 988 | reference operator[]( size_type idx ) nsrs_noexcept 989 | { 990 | return m_rs->at_(m_idx + idx); 991 | } 992 | 993 | const reference operator[]( size_type idx ) const nsrs_noexcept 994 | { 995 | return m_rs->at_(m_idx + idx); 996 | } 997 | #endif 998 | 999 | // advance iterator: 1000 | 1001 | type & operator++() nsrs_noexcept 1002 | { 1003 | ++m_idx; return *this; 1004 | } 1005 | 1006 | type operator++( int ) nsrs_noexcept 1007 | { 1008 | type r(*this); ++*this; return r; 1009 | } 1010 | 1011 | type & operator--() nsrs_noexcept 1012 | { 1013 | --m_idx; return *this; 1014 | } 1015 | 1016 | type operator--( int ) nsrs_noexcept 1017 | { 1018 | type r(*this); --*this; return r; 1019 | } 1020 | 1021 | #if defined(__clang__) || defined(__GNUC__) 1022 | # pragma GCC diagnostic push 1023 | # pragma GCC diagnostic ignored "-Wsign-conversion" 1024 | #endif 1025 | 1026 | type & operator+=( int i ) nsrs_noexcept 1027 | { 1028 | m_idx += i; return *this; 1029 | } 1030 | 1031 | type & operator-=( int i ) nsrs_noexcept 1032 | { 1033 | m_idx -= i; return *this; 1034 | } 1035 | 1036 | #if defined(__clang__) || defined(__GNUC__) 1037 | # pragma GCC diagnostic pop 1038 | #endif 1039 | 1040 | #if nsrs_RING_SPAN_LITE_EXTENSION 1041 | 1042 | template< bool C > 1043 | difference_type operator-( ring_iterator const & rhs ) const nsrs_noexcept 1044 | { 1045 | return static_cast( this->m_idx ) - static_cast( rhs.m_idx ); 1046 | } 1047 | #endif 1048 | 1049 | // comparison: 1050 | 1051 | template< bool C > 1052 | bool operator<( ring_iterator const & rhs ) const nsrs_noexcept 1053 | { 1054 | assert( this->m_rs == rhs.m_rs ); return ( this->m_idx < rhs.m_idx ); 1055 | } 1056 | 1057 | template< bool C > 1058 | bool operator==( ring_iterator const & rhs ) const nsrs_noexcept 1059 | { 1060 | assert( this->m_rs == rhs.m_rs ); return ( this->m_idx == rhs.m_idx ); 1061 | } 1062 | 1063 | // other comparisons expressed in <, ==: 1064 | 1065 | template< bool C > 1066 | inline bool operator!=( ring_iterator const & rhs ) const nsrs_noexcept 1067 | { 1068 | return ! ( *this == rhs ); 1069 | } 1070 | 1071 | template< bool C > 1072 | inline bool operator<=( ring_iterator const & rhs ) const nsrs_noexcept 1073 | { 1074 | return ! ( rhs < *this ); 1075 | } 1076 | 1077 | template< bool C > 1078 | inline bool operator>( ring_iterator const & rhs ) const nsrs_noexcept 1079 | { 1080 | return rhs < *this; 1081 | } 1082 | 1083 | template< bool C > 1084 | inline bool operator>=( ring_iterator const & rhs ) const nsrs_noexcept 1085 | { 1086 | return ! ( *this < rhs ); 1087 | } 1088 | 1089 | private: 1090 | friend class ring_iterator; 1091 | 1092 | typedef typename std11::conditional::type ring_type; 1093 | 1094 | ring_iterator( size_type idx, typename std11::conditional::type * rs ) nsrs_noexcept 1095 | : m_idx( idx ) 1096 | , m_rs ( rs ) 1097 | {} 1098 | 1099 | private: 1100 | size_type m_idx; 1101 | ring_type * m_rs; 1102 | }; 1103 | 1104 | // advanced iterator: 1105 | 1106 | template< class RS, bool C > 1107 | inline ring_iterator operator+( ring_iterator it, int i ) nsrs_noexcept 1108 | { 1109 | it += i; return it; 1110 | } 1111 | 1112 | template< class RS, bool C > 1113 | inline ring_iterator operator+( int i, ring_iterator it ) nsrs_noexcept 1114 | { 1115 | it += i; return it; 1116 | } 1117 | 1118 | template< class RS, bool C > 1119 | inline ring_iterator operator-( ring_iterator it, int i ) nsrs_noexcept 1120 | { 1121 | it -= i; return it; 1122 | } 1123 | 1124 | } // namespace detail 1125 | } // namespace ring_span_lite 1126 | 1127 | using ring_span_lite::ring_span; 1128 | using ring_span_lite::null_popper; 1129 | using ring_span_lite::default_popper; 1130 | using ring_span_lite::copy_popper; 1131 | 1132 | } // namespace nonstd 1133 | 1134 | nsrs_RESTORE_WARNINGS() 1135 | 1136 | #endif // NONSTD_RING_SPAN_LITE_HPP 1137 | -------------------------------------------------------------------------------- /project/CodeBlocks/ring-span-lite.cbp: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 54 | 55 | -------------------------------------------------------------------------------- /project/CodeBlocks/ring-span-lite.workspace: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /script/create-cov-rpt.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright 2019-2019 by Martin Moene 4 | # 5 | # Distributed under the Boost Software License, Version 1.0. 6 | # (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | # 8 | # script/create-cov-rpt.py, Python 3.4 and later 9 | # 10 | 11 | import argparse 12 | import os 13 | import re 14 | import sys 15 | import subprocess 16 | 17 | # Configuration: 18 | 19 | cfg_github_project = 'ring-span-lite' 20 | cfg_github_user = 'martinmoene' 21 | cfg_prj_folder_level = 3 22 | 23 | tpl_coverage_cmd = 'opencppcoverage --no_aggregate_by_file --sources {src} -- {exe}' 24 | 25 | # End configuration. 26 | 27 | def project_folder( f, args ): 28 | """Project root""" 29 | if args.prj_folder: 30 | return args.prj_folder 31 | return os.path.normpath( os.path.join( os.path.dirname( os.path.abspath(f) ), '../' * args.prj_folder_level ) ) 32 | 33 | def executable_folder( f ): 34 | """Folder where the xecutable is""" 35 | return os.path.dirname( os.path.abspath(f) ) 36 | 37 | def executable_name( f ): 38 | """Folder where the executable is""" 39 | return os.path.basename( f ) 40 | 41 | def createCoverageReport( f, args ): 42 | print( "Creating coverage report for project '{usr}/{prj}', '{file}':". 43 | format( usr=args.user, prj=args.project, file=f ) ) 44 | cmd = tpl_coverage_cmd.format( folder=executable_folder(f), src=project_folder(f, args), exe=executable_name(f) ) 45 | if args.verbose: 46 | print( "> {}".format(cmd) ) 47 | if not args.dry_run: 48 | os.chdir( executable_folder(f) ) 49 | subprocess.call( cmd, shell=False ) 50 | os.chdir( project_folder(f, args) ) 51 | 52 | def createCoverageReports( args ): 53 | for f in args.executable: 54 | createCoverageReport( f, args ) 55 | 56 | def createCoverageReportFromCommandLine(): 57 | """Collect arguments from the commandline and create coverage report.""" 58 | parser = argparse.ArgumentParser( 59 | description='Create coverage report.', 60 | epilog="""""", 61 | formatter_class=argparse.ArgumentDefaultsHelpFormatter) 62 | 63 | parser.add_argument( 64 | 'executable', 65 | metavar='executable', 66 | type=str, 67 | nargs=1, 68 | help='executable to report on') 69 | 70 | parser.add_argument( 71 | '-n', '--dry-run', 72 | action='store_true', 73 | help='do not execute conan commands') 74 | 75 | parser.add_argument( 76 | '-v', '--verbose', 77 | action='count', 78 | default=0, 79 | help='level of progress reporting') 80 | 81 | parser.add_argument( 82 | '--user', 83 | metavar='u', 84 | type=str, 85 | default=cfg_github_user, 86 | help='github user name') 87 | 88 | parser.add_argument( 89 | '--project', 90 | metavar='p', 91 | type=str, 92 | default=cfg_github_project, 93 | help='github project name') 94 | 95 | parser.add_argument( 96 | '--prj-folder', 97 | metavar='f', 98 | type=str, 99 | default=None, 100 | help='project root folder') 101 | 102 | parser.add_argument( 103 | '--prj-folder-level', 104 | metavar='n', 105 | type=int, 106 | default=cfg_prj_folder_level, 107 | help='project root folder level from executable') 108 | 109 | createCoverageReports( parser.parse_args() ) 110 | 111 | if __name__ == '__main__': 112 | createCoverageReportFromCommandLine() 113 | 114 | # end of file 115 | -------------------------------------------------------------------------------- /script/create-vcpkg.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright 2019-2019 by Martin Moene 4 | # 5 | # Distributed under the Boost Software License, Version 1.0. 6 | # (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | # 8 | # script/upload-conan.py, Python 3.4 and later 9 | # 10 | 11 | import argparse 12 | import os 13 | import re 14 | import sys 15 | import subprocess 16 | 17 | # Configuration: 18 | 19 | cfg_github_project = 'ring-span-lite' 20 | cfg_github_user = 'martinmoene' 21 | cfg_description = '(unused)' 22 | 23 | cfg_cmakelists = 'CMakeLists.txt' 24 | cfg_readme = 'Readme.md' 25 | cfg_license = 'LICENSE.txt' 26 | cfg_ref_prefix = 'v' 27 | 28 | cfg_sha512 = 'dadeda' 29 | cfg_vcpkg_description = '(no description found)' 30 | cfg_vcpkg_root = os.environ['VCPKG_ROOT'] 31 | 32 | cfg_cmake_optpfx = "RING_SPAN_LITE" 33 | 34 | # End configuration. 35 | 36 | # vcpkg control and port templates: 37 | 38 | tpl_path_vcpkg_control = '{vcpkg}/ports/{prj}/CONTROL' 39 | tpl_path_vcpkg_portfile = '{vcpkg}/ports/{prj}/portfile.cmake' 40 | 41 | tpl_vcpkg_control =\ 42 | """Source: {prj} 43 | Version: {ver} 44 | Description: {desc}""" 45 | 46 | tpl_vcpkg_portfile =\ 47 | """include(vcpkg_common_functions) 48 | 49 | vcpkg_from_github( 50 | OUT_SOURCE_PATH SOURCE_PATH 51 | REPO {usr}/{prj} 52 | REF {ref} 53 | SHA512 {sha} 54 | ) 55 | 56 | vcpkg_configure_cmake( 57 | SOURCE_PATH ${{SOURCE_PATH}} 58 | PREFER_NINJA 59 | OPTIONS 60 | -D{optpfx}_OPT_BUILD_TESTS=OFF 61 | -D{optpfx}_OPT_BUILD_EXAMPLES=OFF 62 | ) 63 | 64 | vcpkg_install_cmake() 65 | 66 | vcpkg_fixup_cmake_targets( 67 | CONFIG_PATH lib/cmake/${{PORT}} 68 | ) 69 | 70 | file(REMOVE_RECURSE 71 | ${{CURRENT_PACKAGES_DIR}}/debug 72 | ${{CURRENT_PACKAGES_DIR}}/lib 73 | ) 74 | 75 | file(INSTALL 76 | ${{SOURCE_PATH}}/{lic} DESTINATION ${{CURRENT_PACKAGES_DIR}}/share/${{PORT}} RENAME copyright 77 | )""" 78 | 79 | tpl_vcpkg_note_sha =\ 80 | """ 81 | Next actions: 82 | - Obtain package SHA: 'vcpkg install {prj}', copy SHA mentioned in 'Actual hash: [...]' 83 | - Add SHA to package: 'script\create-vcpkg --sha={sha}' 84 | - Install package : 'vcpkg install {prj}'""" 85 | 86 | tpl_vcpkg_note_install =\ 87 | """ 88 | Next actions: 89 | - Install package: 'vcpkg install {prj}'""" 90 | 91 | # End of vcpkg templates 92 | 93 | def versionFrom( filename ): 94 | """Obtain version from CMakeLists.txt""" 95 | with open( filename, 'r' ) as f: 96 | content = f.read() 97 | version = re.search(r'VERSION\s(\d+\.\d+\.\d+)', content).group(1) 98 | return version 99 | 100 | def descriptionFrom( filename ): 101 | """Obtain description from CMakeLists.txt""" 102 | with open( filename, 'r' ) as f: 103 | content = f.read() 104 | description = re.search(r'DESCRIPTION\s"(.*)"', content).group(1) 105 | return description if description else cfg_vcpkg_description 106 | 107 | def vcpkgRootFrom( path ): 108 | return path if path else './vcpkg' 109 | 110 | def to_ref( version ): 111 | """Add prefix to version/tag, like v1.2.3""" 112 | return cfg_ref_prefix + version 113 | 114 | def control_path( args ): 115 | """Create path like vcpks/ports/_project_/CONTROL""" 116 | return tpl_path_vcpkg_control.format( vcpkg=args.vcpkg_root, prj=args.project ) 117 | 118 | def portfile_path( args ): 119 | """Create path like vcpks/ports/_project_/portfile.cmake""" 120 | return tpl_path_vcpkg_portfile.format( vcpkg=args.vcpkg_root, prj=args.project ) 121 | 122 | def createControl( args ): 123 | """Create vcpkg CONTROL file""" 124 | output = tpl_vcpkg_control.format( 125 | prj=args.project, ver=args.version, desc=args.description ) 126 | if args.verbose: 127 | print( "Creating control file '{f}':".format( f=control_path( args ) ) ) 128 | if args.verbose > 1: 129 | print( output ) 130 | os.makedirs( os.path.dirname( control_path( args ) ), exist_ok=True ) 131 | with open( control_path( args ), 'w') as f: 132 | print( output, file=f ) 133 | 134 | def createPortfile( args ): 135 | """Create vcpkg portfile""" 136 | output = tpl_vcpkg_portfile.format( 137 | optpfx=cfg_cmake_optpfx, usr=args.user, prj=args.project, ref=to_ref(args.version), sha=args.sha, lic=cfg_license ) 138 | if args.verbose: 139 | print( "Creating portfile '{f}':".format( f=portfile_path( args ) ) ) 140 | if args.verbose > 1: 141 | print( output ) 142 | os.makedirs( os.path.dirname( portfile_path( args ) ), exist_ok=True ) 143 | with open( portfile_path( args ), 'w') as f: 144 | print( output, file=f ) 145 | 146 | def printNotes( args ): 147 | if args.sha == cfg_sha512: 148 | print( tpl_vcpkg_note_sha. 149 | format( prj=args.project, sha='...' ) ) 150 | else: 151 | print( tpl_vcpkg_note_install. 152 | format( prj=args.project ) ) 153 | 154 | def createVcpkg( args ): 155 | print( "Creating vcpkg for '{usr}/{prj}', version '{ver}' in folder '{vcpkg}':". 156 | format( usr=args.user, prj=args.project, ver=args.version, vcpkg=args.vcpkg_root, ) ) 157 | createControl( args ) 158 | createPortfile( args ) 159 | printNotes( args ) 160 | 161 | def createVcpkgFromCommandLine(): 162 | """Collect arguments from the commandline and create vcpkg.""" 163 | 164 | parser = argparse.ArgumentParser( 165 | description='Create microsoft vcpkg.', 166 | epilog="""""", 167 | formatter_class=argparse.ArgumentDefaultsHelpFormatter) 168 | 169 | parser.add_argument( 170 | '-v', '--verbose', 171 | action='count', 172 | default=0, 173 | help='level of progress reporting') 174 | 175 | parser.add_argument( 176 | '--user', 177 | metavar='u', 178 | type=str, 179 | default=cfg_github_user, 180 | help='github user name') 181 | 182 | parser.add_argument( 183 | '--project', 184 | metavar='p', 185 | type=str, 186 | default=cfg_github_project, 187 | help='github project name') 188 | 189 | parser.add_argument( 190 | '--description', 191 | metavar='d', 192 | type=str, 193 | # default=cfg_description, 194 | default=descriptionFrom( cfg_cmakelists ), 195 | help='vcpkg description [from ' + cfg_cmakelists + ']') 196 | 197 | parser.add_argument( 198 | '--version', 199 | metavar='v', 200 | type=str, 201 | default=versionFrom( cfg_cmakelists ), 202 | help='version number [from ' + cfg_cmakelists + ']') 203 | 204 | parser.add_argument( 205 | '--sha', 206 | metavar='s', 207 | type=str, 208 | default=cfg_sha512, 209 | help='sha of package') 210 | 211 | parser.add_argument( 212 | '--vcpkg-root', 213 | metavar='r', 214 | type=str, 215 | default=vcpkgRootFrom( cfg_vcpkg_root ), 216 | help='parent folder containing ports to write files to') 217 | 218 | createVcpkg( parser.parse_args() ) 219 | 220 | if __name__ == '__main__': 221 | createVcpkgFromCommandLine() 222 | 223 | # end of file 224 | -------------------------------------------------------------------------------- /script/update-version.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright 2017-2018 by Martin Moene 4 | # 5 | # Distributed under the Boost Software License, Version 1.0. 6 | # (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | # 8 | # script/update-version.py 9 | # 10 | 11 | from __future__ import print_function 12 | 13 | import argparse 14 | import os 15 | import re 16 | import sys 17 | 18 | # Configuration: 19 | 20 | table = ( 21 | # path, substitute find, substitute format 22 | ( 'CMakeLists.txt' 23 | , r'\W{2,4}VERSION\W+([0-9]+\.[0-9]+\.[0-9]+)\W*$' 24 | , ' VERSION {major}.{minor}.{patch}' ) 25 | 26 | , ( 'CMakeLists.txt' 27 | , r'set\W+ring_span_lite_version\W+"([0-9]+\.[0-9]+\.[0-9]+)"\W+$' 28 | , 'set( ring_span_lite_version "{major}.{minor}.{patch}" )\n' ) 29 | 30 | # , ( 'example/cmake-pkg/CMakeLists.txt' 31 | # , r'set\W+ring_span_lite_version\W+"([0-9]+\.[0-9]+(\.[0-9]+)?)"\W+$' 32 | # , 'set( ring_span_lite_version "{major}.{minor}" )\n' ) 33 | # 34 | # , ( 'script/install-xxx-pkg.py' 35 | # , r'\ring_span_lite_version\s+=\s+"([0-9]+\.[0-9]+\.[0-9]+)"\s*$' 36 | # , 'ring_span_lite_version = "{major}.{minor}.{patch}"\n' ) 37 | 38 | , ( 'conanfile.py' 39 | , r'version\s+=\s+"([0-9]+\.[0-9]+\.[0-9]+)"\s*$' 40 | , 'version = "{major}.{minor}.{patch}"' ) 41 | 42 | , ( 'include/nonstd/ring_span.hpp' 43 | , r'\#define\s+ring_span_lite_MAJOR\s+[0-9]+\s*$' 44 | , '#define ring_span_lite_MAJOR {major}' ) 45 | 46 | , ( 'include/nonstd/ring_span.hpp' 47 | , r'\#define\s+ring_span_lite_MINOR\s+[0-9]+\s*$' 48 | , '#define ring_span_lite_MINOR {minor}' ) 49 | 50 | , ( 'include/nonstd/ring_span.hpp' 51 | , r'\#define\s+ring_span_lite_PATCH\s+[0-9]+\s*$' 52 | , '#define ring_span_lite_PATCH {patch}\n' ) 53 | ) 54 | 55 | # End configuration. 56 | 57 | def readFile( in_path ): 58 | """Return content of file at given path""" 59 | with open( in_path, 'r' ) as in_file: 60 | contents = in_file.read() 61 | return contents 62 | 63 | def writeFile( out_path, contents ): 64 | """Write contents to file at given path""" 65 | with open( out_path, 'w' ) as out_file: 66 | out_file.write( contents ) 67 | 68 | def replaceFile( output_path, input_path ): 69 | # prevent race-condition (Python 3.3): 70 | if sys.version_info >= (3, 3): 71 | os.replace( output_path, input_path ) 72 | else: 73 | os.remove( input_path ) 74 | os.rename( output_path, input_path ) 75 | 76 | def editFileToVersion( version, info, verbose ): 77 | """Update version given file path, version regexp and new version format in info""" 78 | major, minor, patch = version.split('.') 79 | in_path, ver_re, ver_fmt = info 80 | out_path = in_path + '.tmp' 81 | new_text = ver_fmt.format( major=major, minor=minor, patch=patch ) 82 | 83 | if verbose: 84 | print( "- {path} => '{text}':".format( path=in_path, text=new_text.strip('\n') ) ) 85 | 86 | writeFile( 87 | out_path, 88 | re.sub( 89 | ver_re, new_text, readFile( in_path ) 90 | , count=0, flags=re.MULTILINE 91 | ) 92 | ) 93 | replaceFile( out_path, in_path ) 94 | 95 | def editFilesToVersion( version, table, verbose ): 96 | if verbose: 97 | print( "Editing files to version {v}:".format(v=version) ) 98 | for item in table: 99 | editFileToVersion( version, item, verbose ) 100 | 101 | def editFilesToVersionFromCommandLine(): 102 | """Update version number given on command line in paths from configuration table.""" 103 | 104 | parser = argparse.ArgumentParser( 105 | description='Update version number in files.', 106 | epilog="""""", 107 | formatter_class=argparse.RawTextHelpFormatter) 108 | 109 | parser.add_argument( 110 | 'version', 111 | metavar='version', 112 | type=str, 113 | nargs=1, 114 | help='new version number, like 1.2.3') 115 | 116 | parser.add_argument( 117 | '-v', '--verbose', 118 | action='store_true', 119 | help='report the name of the file being processed') 120 | 121 | args = parser.parse_args() 122 | 123 | editFilesToVersion( args.version[0], table, args.verbose ) 124 | 125 | 126 | if __name__ == '__main__': 127 | editFilesToVersionFromCommandLine() 128 | 129 | # end of file 130 | -------------------------------------------------------------------------------- /script/upload-conan.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright 2019-2019 by Martin Moene 4 | # 5 | # Distributed under the Boost Software License, Version 1.0. 6 | # (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | # 8 | # script/upload-conan.py 9 | # 10 | 11 | from __future__ import print_function 12 | 13 | import argparse 14 | import os 15 | import re 16 | import sys 17 | import subprocess 18 | 19 | # Configuration: 20 | 21 | def_conan_project = 'ring-span-lite' 22 | def_conan_user = 'nonstd-lite' 23 | def_conan_channel = 'stable' 24 | cfg_conanfile = 'conanfile.py' 25 | 26 | tpl_conan_create = 'conan create . {usr}/{chn}' 27 | tpl_conan_upload = 'conan upload --remote {usr} {prj}/{ver}@{usr}/{chn}' 28 | 29 | # End configuration. 30 | 31 | def versionFrom( filename ): 32 | """Obtain version from conanfile.py""" 33 | with open( filename ) as f: 34 | content = f.read() 35 | version = re.search(r'version\s=\s"(.*)"', content).group(1) 36 | return version 37 | 38 | def createConanPackage( args ): 39 | """Create conan package and upload it.""" 40 | cmd = tpl_conan_create.format(usr=args.user, chn=args.channel) 41 | if args.verbose: 42 | print( "> {}".format(cmd) ) 43 | if not args.dry_run: 44 | subprocess.call( cmd, shell=False ) 45 | 46 | def uploadConanPackage( args ): 47 | """Create conan package and upload it.""" 48 | cmd = tpl_conan_upload.format(prj=args.project, usr=args.user, chn=args.channel, ver=args.version) 49 | if args.verbose: 50 | print( "> {}".format(cmd) ) 51 | if not args.dry_run: 52 | subprocess.call( cmd, shell=False ) 53 | 54 | def uploadToConan( args ): 55 | """Create conan package and upload it.""" 56 | print( "Updating project '{prj}' to user '{usr}', channel '{chn}', version {ver}:". 57 | format(prj=args.project, usr=args.user, chn=args.channel, ver=args.version) ) 58 | createConanPackage( args ) 59 | uploadConanPackage( args ) 60 | 61 | def uploadToConanFromCommandLine(): 62 | """Collect arguments from the commandline and create conan package and upload it.""" 63 | 64 | parser = argparse.ArgumentParser( 65 | description='Create conan package and upload it to conan.', 66 | epilog="""""", 67 | formatter_class=argparse.ArgumentDefaultsHelpFormatter) 68 | 69 | parser.add_argument( 70 | '-n', '--dry-run', 71 | action='store_true', 72 | help='do not execute conan commands') 73 | 74 | parser.add_argument( 75 | '-v', '--verbose', 76 | action='count', 77 | default=0, 78 | help='level of progress reporting') 79 | 80 | parser.add_argument( 81 | '--project', 82 | metavar='p', 83 | type=str, 84 | default=def_conan_project, 85 | help='conan project') 86 | 87 | parser.add_argument( 88 | '--user', 89 | metavar='u', 90 | type=str, 91 | default=def_conan_user, 92 | help='conan user') 93 | 94 | parser.add_argument( 95 | '--channel', 96 | metavar='c', 97 | type=str, 98 | default=def_conan_channel, 99 | help='conan channel') 100 | 101 | parser.add_argument( 102 | '--version', 103 | metavar='v', 104 | type=str, 105 | default=versionFrom( cfg_conanfile ), 106 | help='version number [from conanfile.py]') 107 | 108 | uploadToConan( parser.parse_args() ) 109 | 110 | 111 | if __name__ == '__main__': 112 | uploadToConanFromCommandLine() 113 | 114 | # end of file 115 | -------------------------------------------------------------------------------- /test/BUCK: -------------------------------------------------------------------------------- 1 | cxx_binary( 2 | name = 'test', 3 | header_namespace = '', 4 | headers = glob([ 5 | '*.hpp', 6 | ]), 7 | srcs = glob([ 8 | '*.cpp', 9 | ]), 10 | compiler_flags = [ 11 | '-std=c++11', 12 | ], 13 | deps = [ 14 | '//:ring-span-lite', 15 | ], 16 | ) 17 | -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2017-2018 Martin Moene 2 | # 3 | # https://github.com/martinmoene/ring-span-lite 4 | # 5 | # Distributed under the Boost Software License, Version 1.0. 6 | # (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | 8 | if( NOT DEFINED CMAKE_MINIMUM_REQUIRED_VERSION ) 9 | cmake_minimum_required( VERSION 3.5 FATAL_ERROR ) 10 | endif() 11 | 12 | option( RING_SPAN_LITE_COLOURISE_TEST "Colourise test output" OFF ) 13 | 14 | project( test LANGUAGES CXX ) 15 | 16 | set( unit_name "ring-span" ) 17 | set( PACKAGE ${unit_name}-lite ) 18 | set( PROGRAM ${unit_name}-lite ) 19 | set( SOURCES ${unit_name}-main.t.cpp ${unit_name}.t.cpp ) 20 | set( TWEAKD "." ) 21 | 22 | message( STATUS "Subproject '${PROJECT_NAME}', programs '${PROGRAM}-*'") 23 | 24 | # Configure ring-span-lite for testing: 25 | 26 | set( OPTIONS "" ) 27 | set( RING_SPAN_CONFIG "" ) 28 | 29 | if( RING_SPAN_LITE_COLOURISE_TEST ) 30 | set( LEST_COLOURISE -Dlest_FEATURE_COLOURISE=1 ) 31 | endif() 32 | 33 | set( HAS_STD_FLAGS FALSE ) 34 | set( HAS_CPP98_FLAG FALSE ) 35 | set( HAS_CPP11_FLAG FALSE ) 36 | set( HAS_CPP14_FLAG FALSE ) 37 | set( HAS_CPP17_FLAG FALSE ) 38 | set( HAS_CPP20_FLAG FALSE ) 39 | set( HAS_CPPLATEST_FLAG FALSE ) 40 | 41 | if( MSVC ) 42 | message( STATUS "Matched: MSVC") 43 | 44 | set( HAS_STD_FLAGS TRUE ) 45 | 46 | set( OPTIONS -W3 -EHsc ) 47 | set( DEFINITIONS -D_SCL_SECURE_NO_WARNINGS ${RING_SPAN_CONFIG} ${LEST_COLOURISE} ) 48 | 49 | if( NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.00 ) 50 | set( HAS_CPP14_FLAG TRUE ) 51 | set( HAS_CPPLATEST_FLAG TRUE ) 52 | endif() 53 | if( NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.11 ) 54 | set( HAS_CPP17_FLAG TRUE ) 55 | endif() 56 | 57 | elseif( CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|AppleClang" ) 58 | message( STATUS "CompilerId: '${CMAKE_CXX_COMPILER_ID}'") 59 | 60 | set( HAS_STD_FLAGS TRUE ) 61 | set( HAS_CPP98_FLAG TRUE ) 62 | 63 | set( OPTIONS -Wall -Wextra -Wconversion -Wsign-conversion -Wno-missing-braces -fno-elide-constructors -Wconversion -Wsign-conversion ) 64 | set( DEFINITIONS ${RING_SPAN_CONFIG} ${LEST_COLOURISE} ) 65 | 66 | # GNU: available -std flags depends on version 67 | if( CMAKE_CXX_COMPILER_ID MATCHES "GNU" ) 68 | message( STATUS "Matched: GNU") 69 | 70 | if( NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.8.0 ) 71 | set( HAS_CPP11_FLAG TRUE ) 72 | endif() 73 | if( NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.9.2 ) 74 | set( HAS_CPP14_FLAG TRUE ) 75 | endif() 76 | if( NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 7.1.0 ) 77 | set( HAS_CPP17_FLAG TRUE ) 78 | endif() 79 | 80 | # AppleClang: available -std flags depends on version 81 | elseif( CMAKE_CXX_COMPILER_ID MATCHES "AppleClang" ) 82 | message( STATUS "Matched: AppleClang") 83 | 84 | if( NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0.0 ) 85 | set( HAS_CPP11_FLAG TRUE ) 86 | endif() 87 | if( NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.1.0 ) 88 | set( HAS_CPP14_FLAG TRUE ) 89 | endif() 90 | if( NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9.2.0 ) 91 | set( HAS_CPP17_FLAG TRUE ) 92 | endif() 93 | 94 | # Clang: available -std flags depends on version 95 | elseif( CMAKE_CXX_COMPILER_ID MATCHES "Clang" ) 96 | message( STATUS "Matched: Clang") 97 | 98 | if( NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.3.0 ) 99 | set( HAS_CPP11_FLAG TRUE ) 100 | endif() 101 | if( NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.4.0 ) 102 | set( HAS_CPP14_FLAG TRUE ) 103 | endif() 104 | if( NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0.0 ) 105 | set( HAS_CPP17_FLAG TRUE ) 106 | endif() 107 | endif() 108 | 109 | elseif( CMAKE_CXX_COMPILER_ID MATCHES "Intel" ) 110 | # as is 111 | message( STATUS "Matched: Intel") 112 | else() 113 | # as is 114 | message( STATUS "Matched: nothing") 115 | endif() 116 | 117 | # enable MS C++ Core Guidelines checker if MSVC: 118 | 119 | function( enable_msvs_guideline_checker target ) 120 | if( MSVC ) 121 | set_target_properties( ${target} PROPERTIES 122 | VS_GLOBAL_EnableCppCoreCheck true 123 | VS_GLOBAL_CodeAnalysisRuleSet CppCoreCheckRules.ruleset 124 | VS_GLOBAL_RunCodeAnalysis true ) 125 | endif() 126 | endfunction() 127 | 128 | # make target, compile for given standard if specified: 129 | 130 | function( make_target target std ) 131 | message( STATUS "Make target: '${std}'" ) 132 | 133 | add_executable ( ${target} ${SOURCES} ) 134 | target_include_directories( ${target} SYSTEM PRIVATE lest ) 135 | target_include_directories( ${target} PRIVATE ${TWEAKD} ) 136 | target_link_libraries ( ${target} PRIVATE ${PACKAGE} ) 137 | target_compile_options ( ${target} PRIVATE ${OPTIONS} ) 138 | target_compile_definitions( ${target} PRIVATE ${DEFINITIONS} ) 139 | 140 | if( std ) 141 | if( MSVC ) 142 | target_compile_options( ${target} PRIVATE -std:c++${std} ) 143 | else() 144 | # Necessary for clang 3.x: 145 | target_compile_options( ${target} PRIVATE -std=c++${std} ) 146 | # Ok for clang 4 and later: 147 | # set( CMAKE_CXX_STANDARD ${std} ) 148 | # set( CMAKE_CXX_STANDARD_REQUIRED ON ) 149 | # set( CMAKE_CXX_EXTENSIONS OFF ) 150 | endif() 151 | endif() 152 | endfunction() 153 | 154 | # add generic executable, unless -std flags can be specified: 155 | 156 | if( NOT HAS_STD_FLAGS ) 157 | make_target( ${PROGRAM}.t "" ) 158 | else() 159 | # unconditionally add C++98 variant as MSVC has no option for it: 160 | if( HAS_CPP98_FLAG ) 161 | make_target( ${PROGRAM}-cpp98.t 98 ) 162 | else() 163 | make_target( ${PROGRAM}-cpp98.t "" ) 164 | endif() 165 | 166 | if( HAS_CPP11_FLAG ) 167 | make_target( ${PROGRAM}-cpp11.t 11 ) 168 | endif() 169 | 170 | if( HAS_CPP14_FLAG ) 171 | make_target( ${PROGRAM}-cpp14.t 14 ) 172 | endif() 173 | 174 | if( HAS_CPP17_FLAG ) 175 | set( std17 17 ) 176 | if( CMAKE_CXX_COMPILER_ID MATCHES "AppleClang" ) 177 | set( std17 1z ) 178 | endif() 179 | make_target( ${PROGRAM}-cpp17.t ${std17} ) 180 | enable_msvs_guideline_checker( ${PROGRAM}-cpp17.t ) 181 | endif() 182 | 183 | if( HAS_CPPLATEST_FLAG ) 184 | make_target( ${PROGRAM}-cpplatest.t latest ) 185 | endif() 186 | endif() 187 | 188 | # with C++20?, honour explicit request for std::any or nonstd::any: 189 | 190 | if( HAS_CPP20_FLAG ) 191 | set( WHICH nsrs_RING_SPAN_DEFAULT ) 192 | 193 | if( ANY_LITE_OPT_SELECT_STD ) 194 | set( WHICH nsrs_RING_SPAN_STD ) 195 | elseif( ANY_LITE_OPT_SELECT_NONSTD ) 196 | set( WHICH nsrs_RING_SPAN_NONSTD ) 197 | endif() 198 | 199 | target_compile_definitions( ${PROGRAM}-cpp20.t PRIVATE nsrs_CONFIG_SELECT_RING_SPAN=${WHICH} ) 200 | 201 | if( HAS_CPPLATEST_FLAG ) 202 | target_compile_definitions( ${PROGRAM}-cpplatest.t PRIVATE nsrs_CONFIG_SELECT_RING_SPAN=${WHICH} ) 203 | endif() 204 | endif() 205 | 206 | # configure unit tests via CTest: 207 | 208 | enable_testing() 209 | 210 | if( HAS_STD_FLAGS ) 211 | # unconditionally add C++98 variant for MSVC: 212 | add_test( NAME test-cpp98 COMMAND ${PROGRAM}-cpp98.t ) 213 | 214 | if( HAS_CPP11_FLAG ) 215 | add_test( NAME test-cpp11 COMMAND ${PROGRAM}-cpp11.t ) 216 | endif() 217 | if( HAS_CPP14_FLAG ) 218 | add_test( NAME test-cpp14 COMMAND ${PROGRAM}-cpp14.t ) 219 | endif() 220 | if( HAS_CPP17_FLAG ) 221 | add_test( NAME test-cpp17 COMMAND ${PROGRAM}-cpp17.t ) 222 | endif() 223 | if( HAS_CPP20_FLAG ) 224 | add_test( NAME test-cpp20 COMMAND ${PROGRAM}-cpp20.t ) 225 | endif() 226 | if( HAS_CPPLATEST_FLAG ) 227 | add_test( NAME test-cpplatest COMMAND ${PROGRAM}-cpplatest.t ) 228 | endif() 229 | else() 230 | add_test( NAME test COMMAND ${PROGRAM}.t --pass ) 231 | add_test( NAME list_version COMMAND ${PROGRAM}.t --version ) 232 | add_test( NAME list_tags COMMAND ${PROGRAM}.t --list-tags ) 233 | add_test( NAME list_tests COMMAND ${PROGRAM}.t --list-tests ) 234 | endif() 235 | 236 | # end of file 237 | -------------------------------------------------------------------------------- /test/nonstd/ring_span.tweak.hpp: -------------------------------------------------------------------------------- 1 | #define RING_SPAN_TWEAK_VALUE 42 2 | -------------------------------------------------------------------------------- /test/ring-span-main.t.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2017-2018 by Martin Moene 2 | // 3 | // https://github.com/martinmoene/ring-span-lite 4 | // 5 | // Distributed under the Boost Software License, Version 1.0. 6 | // (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | 8 | #ifndef nsrs_RING_SPAN_LITE_T_HEADER 9 | #define nsrs_RING_SPAN_LITE_T_HEADER "ring-span-main.t.hpp" 10 | #endif 11 | 12 | #include nsrs_RING_SPAN_LITE_T_HEADER 13 | 14 | #define nsrs_PRESENT( x ) \ 15 | std::cout << #x << ": " << x << "\n" 16 | 17 | #define nsrs_ABSENT( x ) \ 18 | std::cout << #x << ": (undefined)\n" 19 | 20 | lest::tests & specification() 21 | { 22 | static lest::tests tests; 23 | return tests; 24 | } 25 | 26 | CASE( "ring-span-lite version" "[.ring-span]][.version]" ) 27 | { 28 | nsrs_PRESENT( ring_span_lite_MAJOR ); 29 | nsrs_PRESENT( ring_span_lite_MINOR ); 30 | nsrs_PRESENT( ring_span_lite_PATCH ); 31 | nsrs_PRESENT( ring_span_lite_VERSION ); 32 | } 33 | 34 | CASE( "ring-span-lite configuration" "[.ring-span][.config]" ) 35 | { 36 | nsrs_PRESENT( nsrs_HAVE_TWEAK_HEADER ); 37 | nsrs_PRESENT( nsrs_CONFIG_STRICT_P0059 ); 38 | nsrs_PRESENT( nsrs_CONFIG_POPPER_EMPTY_BASE_CLASS ); 39 | nsrs_PRESENT( nsrs_HAVE_STD_RING_SPAN ); 40 | nsrs_PRESENT( nsrs_USES_STD_RING_SPAN ); 41 | nsrs_PRESENT( nsrs_RING_SPAN_DEFAULT ); 42 | nsrs_PRESENT( nsrs_RING_SPAN_NONSTD ); 43 | nsrs_PRESENT( nsrs_RING_SPAN_STD ); 44 | nsrs_PRESENT( nsrs_CONFIG_SELECT_RING_SPAN ); 45 | // nsrs_PRESENT( nsrs_CONFIG_NO_EXCEPTIONS ); 46 | nsrs_PRESENT( nsrs_CPLUSPLUS ); 47 | 48 | int arr[] = { 7, 7, 7, }; nonstd::ring_span rs( arr, arr + 3 ); 49 | std::cout << "sizeof( nonstd::ring_span() ): " << sizeof(rs) << "\n"; 50 | } 51 | 52 | CASE( "C++ language: __cplusplus" "[.stdc++]" ) 53 | { 54 | nsrs_PRESENT( __cplusplus ); 55 | 56 | #ifdef _MSVC_LANG 57 | nsrs_PRESENT( _MSVC_LANG ); 58 | #else 59 | nsrs_ABSENT( _MSVC_LANG ); 60 | #endif 61 | } 62 | 63 | CASE( "C++ compiler: compiler version" "[.compiler]" ) 64 | { 65 | #if nsrs_USES_STD_RING_SPAN 66 | std::cout << "(Compiler version not available: using std::ring_span)\n"; 67 | #else 68 | nsrs_PRESENT( nsrs_COMPILER_CLANG_VERSION ); 69 | nsrs_PRESENT( nsrs_COMPILER_GNUC_VERSION ); 70 | nsrs_PRESENT( nsrs_COMPILER_MSVC_VERSION ); 71 | #endif 72 | } 73 | 74 | CASE( "Presence of C++ language features" "[.stdlanguage]" ) 75 | { 76 | #if nsrs_USES_STD_RING_SPAN 77 | std::cout << "(Presence of C++ language features not available: using std::ring_span)\n"; 78 | #else 79 | nsrs_PRESENT( nsrs_HAVE_CONSTEXPR_11 ); 80 | nsrs_PRESENT( nsrs_HAVE_CONSTEXPR_14 ); 81 | nsrs_PRESENT( nsrs_HAVE_IS_DEFAULT ); 82 | nsrs_PRESENT( nsrs_HAVE_IS_DELETE ); 83 | nsrs_PRESENT( nsrs_HAVE_NOEXCEPT ); 84 | nsrs_PRESENT( nsrs_HAVE_NULLPTR ); 85 | nsrs_PRESENT( nsrs_HAVE_NO_UNIQUE_ADDRESS ); 86 | #endif 87 | } 88 | 89 | CASE( "Presence of C++ library features" "[.stdlibrary]" ) 90 | { 91 | #if nsrs_USES_STD_RING_SPAN 92 | std::cout << "(Presence of C++ library features not available: using std::ring_span)\n"; 93 | #else 94 | // none 95 | #endif 96 | 97 | #if defined _HAS_CPP0X 98 | nsrs_PRESENT( _HAS_CPP0X ); 99 | #else 100 | nsrs_ABSENT( _HAS_CPP0X ); 101 | #endif 102 | } 103 | 104 | int main( int argc, char * argv[] ) 105 | { 106 | return lest::run( specification(), argc, argv ); 107 | } 108 | 109 | #if 0 110 | g++ -I../include -o ring-span-main.t.exe ring-span-main.t.cpp ring-span.t.cpp && ring-span-main.t.exe --pass 111 | g++ -std=c++98 -I../include -o ring-span-main.t.exe ring-span-main.t.cpp ring-span.t.cpp && ring-span-main.t.exe --pass 112 | g++ -std=c++03 -I../include -o ring-span-main.t.exe ring-span-main.t.cpp ring-span.t.cpp && ring-span-main.t.exe --pass 113 | g++ -std=c++0x -I../include -o ring-span-main.t.exe ring-span-main.t.cpp ring-span.t.cpp && ring-span-main.t.exe --pass 114 | g++ -std=c++11 -I../include -o ring-span-main.t.exe ring-span-main.t.cpp ring-span.t.cpp && ring-span-main.t.exe --pass 115 | g++ -std=c++14 -I../include -o ring-span-main.t.exe ring-span-main.t.cpp ring-span.t.cpp && ring-span-main.t.exe --pass 116 | g++ -std=c++17 -I../include -o ring-span-main.t.exe ring-span-main.t.cpp ring-span.t.cpp && ring-span-main.t.exe --pass 117 | 118 | cl -EHsc -I../include ring-span-main.t.cpp ring-span.t.cpp && ring-span-main.t.exe --pass 119 | #endif 120 | 121 | // end of file 122 | -------------------------------------------------------------------------------- /test/ring-span-main.t.hpp: -------------------------------------------------------------------------------- 1 | // Copyright 2017-2018 by Martin Moene 2 | // 3 | // https://github.com/martinmoene/ring-span-lite 4 | // 5 | // Distributed under the Boost Software License, Version 1.0. 6 | // (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | 8 | #pragma once 9 | 10 | #ifndef RING_SPAN_LITE_T_INCLUDED 11 | #define RING_SPAN_LITE_T_INCLUDED 12 | 13 | #include "nonstd/ring.hpp" 14 | #include "nonstd/ring_span.hpp" 15 | 16 | // Compiler warning suppression for usage of lest: 17 | 18 | #ifdef __clang__ 19 | # pragma clang diagnostic ignored "-Wstring-conversion" 20 | # pragma clang diagnostic ignored "-Wunused-parameter" 21 | # pragma clang diagnostic ignored "-Wunused-template" 22 | # pragma clang diagnostic ignored "-Wunused-function" 23 | # pragma clang diagnostic ignored "-Wunused-member-function" 24 | #elif defined __GNUC__ 25 | # pragma GCC diagnostic ignored "-Wunused-parameter" 26 | # pragma GCC diagnostic ignored "-Wunused-function" 27 | #endif 28 | 29 | #include "lest_cpp03.hpp" 30 | 31 | #define CASE( name ) lest_CASE( specification(), name ) 32 | 33 | // Attribute externally visible for -fwhole-program: 34 | 35 | #if defined(__GNUC__) && !defined(__clang__) 36 | # define any_ATTRIBUTE_EXT_VIS __attribute__((externally_visible)) 37 | #else 38 | # define any_ATTRIBUTE_EXT_VIS 39 | #endif 40 | 41 | extern lest::tests & specification() any_ATTRIBUTE_EXT_VIS; 42 | 43 | namespace nonstd { namespace ring_span_lite { 44 | 45 | // use oparator<< instead of to_string() overload; 46 | // see http://stackoverflow.com/a/10651752/437272 47 | 48 | template< typename T, class Popper> 49 | inline std::ostream & operator<<( std::ostream & os, ring_span const & rs ) 50 | { 51 | #if nsrs_CONFIG_STRICT_P0059 52 | return os << "[ring_span: ???]"; 53 | #else 54 | os << "[ring_span: "; std::copy( rs.begin(), rs.end(), std::ostream_iterator(os, ", ") ); return os << "]"; 55 | #endif 56 | } 57 | 58 | namespace detail { 59 | 60 | template< class RS, bool is_const > 61 | inline std::ostream & operator<<( std::ostream & os, ring_iterator const & it ) 62 | { 63 | #if nsrs_RING_SPAN_LITE_EXTENSION 64 | // Note: hack: depends on iterator implementation to use index [0..size()); 65 | // create begin iterator with index 0 (it and bgn are on different containers!): 66 | typename RS::value_type arr[1]; ring_iterator< RS, true> bgn = RS( arr, arr + 1 ).cbegin(); 67 | 68 | return os << "[ring_iterator: " << (it - bgn) << "]"; 69 | #else 70 | return os << "[ring_iterator: ?]"; 71 | #endif 72 | } 73 | 74 | template< class RS, bool is_const > 75 | inline std::ostream & operator<<( std::ostream & os, std::reverse_iterator< ring_iterator > const & it ) 76 | { 77 | #if nsrs_RING_SPAN_LITE_EXTENSION 78 | // Note: hack: depends on iterator implementation to use index [0..size()); 79 | // create begin iterator with index 0 (it and bgn are on different containers!): 80 | typename RS::value_type arr[1]; std::reverse_iterator< ring_iterator< RS, true> > bgn = RS( arr, arr + 1 ).crbegin(); 81 | 82 | return os << "[reverse ring_iterator: " << -(it - bgn) << "]"; 83 | #else 84 | return os << "[reverse ring_iterator: ?]"; 85 | #endif 86 | } 87 | 88 | } // namespace detail 89 | } // namespace ring_span_lite 90 | } // namespace nonstd 91 | 92 | namespace lest { 93 | 94 | using ::nonstd::ring_span_lite::operator<<; 95 | using ::nonstd::ring_span_lite::detail::operator<<; 96 | 97 | } // namespace lest 98 | 99 | #endif // RING_SPAN_LITE_T_INCLUDED 100 | 101 | // end of file 102 | -------------------------------------------------------------------------------- /test/ring-span-sg14.t.hpp: -------------------------------------------------------------------------------- 1 | // Copyright 2017-2018 by Martin Moene 2 | // 3 | // https://github.com/martinmoene/ring-span-lite 4 | // 5 | // Distributed under the Boost Software License, Version 1.0. 6 | // (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | 8 | #pragma once 9 | 10 | #ifndef ring_span_lite_T_INCLUDED 11 | #define ring_span_lite_T_INCLUDED 12 | 13 | // Compiler detection (C++17 is speculative): 14 | 15 | #define nsrs_CPP11_OR_GREATER ( __cplusplus >= 201103L ) 16 | #define nsrs_CPP14_OR_GREATER ( __cplusplus >= 201402L ) 17 | #define nsrs_CPP17_OR_GREATER ( __cplusplus >= 201700L ) 18 | 19 | // Determine MSVC version (e.g. 14 is VC14, (VS2015/VS2017): 20 | 21 | #if defined(_MSC_VER ) && !defined(__clang__) 22 | # define nsrs_COMPILER_MSVC_VER (_MSC_VER ) 23 | # define nsrs_COMPILER_MSVC_VERSION (_MSC_VER / 10 - 10 * ( 5 + (_MSC_VER < 1900 ) ) ) 24 | #else 25 | # define nsrs_COMPILER_MSVC_VER 0 26 | # define nsrs_COMPILER_MSVC_VERSION 0 27 | #endif 28 | 29 | // Consider VC14 as C++11, C++14 for SG14 ring_span: 30 | 31 | #if nsrs_COMPILER_MSVC_VERSION >= 140 32 | # undef nsrs_CPP11_OR_GREATER 33 | # define nsrs_CPP11_OR_GREATER 1 34 | # undef nsrs_CPP14_OR_GREATER 35 | # define nsrs_CPP14_OR_GREATER 1 36 | #endif 37 | 38 | #include "sg14/sg14-ring.h" 39 | #include "lest_cpp03.hpp" 40 | 41 | using namespace sg14; 42 | 43 | #define ring_span_lite_VERSION "(sg14)" 44 | 45 | #define CASE( name ) lest_CASE( specification(), name ) 46 | 47 | extern lest::tests & specification(); 48 | 49 | namespace sg14 { 50 | 51 | template< typename T, class Popper> 52 | inline std::ostream & operator<<( std::ostream & os, ::sg14::ring_span const & rs ) 53 | { 54 | os << "[ring_span: "; std::copy( rs.begin(), rs.end(), std::ostream_iterator(os, ", ") ); return os << "]"; 55 | } 56 | 57 | template< class RS, bool is_const > 58 | inline std::ostream & operator<<( std::ostream & os, ::sg14::ring_iterator const & it ) 59 | { 60 | return os << "[ring_iterator: ?]"; 61 | } 62 | 63 | } 64 | 65 | namespace lest { 66 | 67 | using ::sg14::operator<<; 68 | 69 | } // namespace lest 70 | 71 | // Provide the following to enable compilation: 72 | 73 | #define ring_span_lite_MAJOR 0 74 | #define ring_span_lite_MINOR 0 75 | #define ring_span_lite_PATCH 0 76 | #define nsrs_HAVE_STD_RING_SPAN 0 77 | #define nsrs_USES_STD_RING_SPAN 0 78 | #define nsrs_RING_SPAN_DEFAULT 0 79 | #define nsrs_RING_SPAN_NONSTD 0 80 | #define nsrs_RING_SPAN_STD 0 81 | #define nsrs_CONFIG_SELECT_RING_SPAN 0 82 | #define nsrs_CPLUSPLUS __cplusplus 83 | #define nsrs_COMPILER_CLANG_VERSION 0 84 | #define nsrs_COMPILER_GNUC_VERSION 0 85 | #define nsrs_HAVE_CONSTEXPR_11 0 86 | #define nsrs_HAVE_CONSTEXPR_14 0 87 | #define nsrs_HAVE_IS_DEFAULT 0 88 | #define nsrs_HAVE_IS_DELETE 0 89 | #define nsrs_HAVE_NOEXCEPT 0 90 | #define nsrs_HAVE_NULLPTR 0 91 | 92 | namespace nonstd{} 93 | 94 | #endif // ring_span_lite_T_INCLUDED 95 | 96 | // end of file 97 | -------------------------------------------------------------------------------- /test/ring-span.t.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // ring-span-lite, a C++yy-like ring span type for C++98 and later. 3 | // For more information see https://github.com/martinmoene/ring-span-lite 4 | // 5 | // Copyright 2017-2018 by Martin Moene 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 | #ifndef nsrs_RING_SPAN_LITE_T_HEADER 11 | #define nsrs_RING_SPAN_LITE_T_HEADER "ring-span-main.t.hpp" 12 | #endif 13 | 14 | #include nsrs_RING_SPAN_LITE_T_HEADER 15 | 16 | #if nsrs_CPP11_OR_GREATER 17 | # include 18 | #endif 19 | 20 | #include 21 | 22 | using namespace nonstd; 23 | 24 | typedef ring_span::size_type size_type; 25 | typedef ring_span::iterator::difference_type difference_type; 26 | 27 | #if nsrs_CPP11_OR_GREATER 28 | 29 | template< typename T, size_t N > 30 | inline constexpr size_t dim( T (&arr)[N] ) 31 | { 32 | return N; 33 | } 34 | #else 35 | # define dim(arr) ( sizeof(arr) / sizeof(0[arr]) ) 36 | #endif 37 | 38 | namespace tst { 39 | 40 | // std::equal() requires iterator::operator-(), 41 | // which is not available with nsrs_CONFIG_STRICT_P0059 42 | 43 | template< typename InputIt1, typename InputIt2 > 44 | bool equal( InputIt1 first1, InputIt1 last1, InputIt2 first2 ) 45 | { 46 | #if nsrs_CONFIG_STRICT_P0059 47 | return true; 48 | #else 49 | return std::equal( first1, last1, first2 ); 50 | #endif 51 | } 52 | 53 | template< typename InputIt1, typename InputIt2, typename T > 54 | T inner_product( InputIt1 first1, InputIt1 last1, InputIt2 first2, T init ) 55 | { 56 | #if nsrs_CONFIG_STRICT_P0059 57 | return init; 58 | #else 59 | return std::inner_product( first1, last1, first2, init ); 60 | #endif 61 | } 62 | 63 | } // namespace tst 64 | 65 | #if nsrs_CPP11_OR_GREATER 66 | struct noncopyable 67 | { 68 | char c; int i; 69 | noncopyable() : c(), i() {} 70 | noncopyable( char k, int x ) : c(k), i(x) {} 71 | noncopyable( noncopyable && ) = default; 72 | noncopyable& operator=( noncopyable && ) = default; 73 | 74 | noncopyable( noncopyable const & ) = delete; 75 | noncopyable& operator=( noncopyable const & ) = delete; 76 | }; 77 | 78 | struct oracle 79 | { 80 | enum state_t { init, moved_from, }; 81 | 82 | static state_t & state() { static state_t s = init; return s; } 83 | static int & value() { static int v = 0; return v; } 84 | 85 | oracle( int v = 0 ) noexcept { state() = init; value() = v; } 86 | oracle( oracle && ) noexcept { state() = moved_from; } 87 | oracle & operator=( oracle && ) noexcept { state() = moved_from; return *this; } 88 | }; 89 | #endif 90 | 91 | CASE( "ring_span: Allows to construct an empty span from an iterator pair" ) 92 | { 93 | int arr[] = { 1, 2, 3, }; 94 | 95 | ring_span rs( &arr[0], &arr[0] + dim(arr) ); 96 | 97 | EXPECT( rs.size() == size_type(0) ); 98 | EXPECT( rs.capacity() == dim(arr) ); 99 | } 100 | 101 | CASE( "ring_span: Allows to construct an empty span from an iterator pair - capacity is power of 2" ) 102 | { 103 | #if nsrs_RING_SPAN_LITE_EXTENSION 104 | int arr[] = { 1, 2, 3, 4, }; 105 | 106 | ring_span, true> rs( &arr[0], &arr[0] + dim(arr) ); 107 | 108 | EXPECT( rs.size() == size_type(0) ); 109 | EXPECT( rs.capacity() == dim(arr) ); 110 | #else 111 | EXPECT( !!"'size is power of 2' is not available (nsrs_CONFIG_STRICT_P0059)" ); 112 | #endif 113 | } 114 | 115 | CASE( "ring_span: Allows to construct a partially filled span from an iterator pair and iterator, size" ) 116 | { 117 | int arr[] = { 7, 7, 1, 2, 3, 7, 7, }; 118 | size_type first = 2; 119 | size_type count = 3; 120 | 121 | ring_span rs( &arr[0], &arr[0] + dim(arr), &arr[0] + first, count ); 122 | 123 | EXPECT( rs.size() == count ); 124 | EXPECT( rs.capacity() == dim(arr) ); 125 | EXPECT( tst::equal( rs.begin(), rs.end(), &arr[0] + first ) ); 126 | } 127 | 128 | CASE( "ring_span: Allows to construct a partially filled span from an iterator pair and iterator, size - capacity is power of 2" ) 129 | { 130 | #if nsrs_RING_SPAN_LITE_EXTENSION 131 | int arr[] = { 7, 7, 1, 2, 3, 7, 7, 8, }; 132 | size_type first = 2; 133 | size_type count = 3; 134 | 135 | ring_span, true> rs( &arr[0], &arr[0] + dim(arr), &arr[0] + first, count ); 136 | 137 | EXPECT( rs.size() == count ); 138 | EXPECT( rs.capacity() == dim(arr) ); 139 | EXPECT( tst::equal( rs.begin(), rs.end(), &arr[0] + first ) ); 140 | #else 141 | EXPECT( !!"'size is power of 2' is not available (nsrs_CONFIG_STRICT_P0059)" ); 142 | #endif 143 | 144 | } 145 | 146 | CASE( "ring_span: Constructing a span with size exceeding capacity asserts m_size <= m_capacity" "[.assert]" ) 147 | { 148 | int arr[] = { 1, 2, 3, 4, 5 }; 149 | 150 | ring_span rs( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr) + 1 ); 151 | } 152 | 153 | CASE( "ring_span: Disallows to copy-construct from a ring_span (compile-time)" ) 154 | { 155 | #if nsrs_CONFIG_CONFIRMS_COMPILATION_ERRORS 156 | int arr[] = { 1, 2, 3, }; ring_span rs1( &arr[0], &arr[0] + dim(arr) ); 157 | 158 | ring_span rs2( rs1 ); 159 | #else 160 | EXPECT( !!"ring_span: check for compile-time error (define nsrs_CONFIG_CONFIRMS_COMPILATION_ERRORS)" ); 161 | #endif 162 | } 163 | 164 | CASE( "ring_span: Disallows to copy-assign from a ring_span (compile-time)" ) 165 | { 166 | #if nsrs_CONFIG_CONFIRMS_COMPILATION_ERRORS 167 | int arr[] = { 1, 2, 3, }; 168 | ring_span rs1( &arr[0], &arr[0] + dim(arr) ); 169 | ring_span rs2( &arr[0], &arr[0] + dim(arr) ); 170 | 171 | rs2 = rs1; 172 | #else 173 | EXPECT( !!"ring_span: check for compile-time error (define nsrs_CONFIG_CONFIRMS_COMPILATION_ERRORS)" ); 174 | #endif 175 | } 176 | 177 | CASE( "ring_span: Allows to move-construct from a ring_span (C++11)" ) 178 | { 179 | #if nsrs_CPP11_OR_GREATER 180 | int arr[] = { 1, 2, 3, }; 181 | 182 | ring_span rs( ring_span( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr) ) ); 183 | 184 | EXPECT( rs.size() == dim(arr) ); 185 | EXPECT( rs.capacity() == dim(arr) ); 186 | EXPECT( tst::equal( rs.begin(), rs.end(), &arr[0] ) ); 187 | #else 188 | EXPECT( !!"ring_span: move-construction is not available (no C++11)" ); 189 | #endif 190 | } 191 | 192 | CASE( "ring_span: Allows to move-assign from a ring_span (C++11)" ) 193 | { 194 | #if nsrs_CPP11_OR_GREATER 195 | int arr[] = { 1, 2, 3, }; ring_span rs( &arr[0], &arr[0] + dim(arr) ); 196 | 197 | rs = ring_span( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr) ); 198 | 199 | EXPECT( rs.size() == dim(arr) ); 200 | EXPECT( rs.capacity() == dim(arr) ); 201 | EXPECT( tst::equal( rs.begin(), rs.end(), &arr[0] ) ); 202 | #else 203 | EXPECT( !!"ring_span: move-assignment is not available (no C++11)" ); 204 | #endif 205 | } 206 | 207 | CASE( "ring_span: Allows to obtain the capacity of a span" ) 208 | { 209 | int arr[] = { 1, 2, 3, }; ring_span rs( &arr[0], &arr[0] + dim(arr) ); 210 | 211 | EXPECT( rs.capacity() == dim(arr) ); 212 | } 213 | 214 | CASE( "ring_span: Allows to obtain the number of elements in a span (size)" ) 215 | { 216 | int arr[] = { 1, 2, 3, }; ring_span rs( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr) ); 217 | 218 | EXPECT( rs.size() == rs.capacity() ); 219 | } 220 | 221 | CASE( "ring_span: Allows to check for an empty span" ) 222 | { 223 | int arr[] = { 1, 2, 3, }; ring_span rs( &arr[0], &arr[0] + dim(arr) ); 224 | 225 | EXPECT( rs.empty() ); 226 | } 227 | 228 | CASE( "ring_span: Allows to check for a full span" ) 229 | { 230 | int arr[] = { 1, 2, 3, }; ring_span rs( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr) ); 231 | 232 | EXPECT( rs.full() ); 233 | } 234 | 235 | CASE( "ring_span: Allows to observe the element at the specified index" " [extension]" ) 236 | { 237 | #if nsrs_CONFIG_STRICT_P0059 238 | EXPECT( !!"operator[] is not available (SG14)" ); 239 | #else 240 | int arr[] = { 1, 2, 3, }; ring_span rs( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr) ); 241 | 242 | EXPECT( rs[0] == arr[0] ); 243 | EXPECT( rs[1] == arr[1] ); 244 | EXPECT( rs[2] == arr[2] ); 245 | #endif 246 | } 247 | 248 | CASE( "ring_span: Allows to observe the element at the front" ) 249 | { 250 | int arr[] = { 1, 2, 3, }; ring_span rs( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr) ); 251 | 252 | EXPECT( rs.front() == arr[0] ); 253 | } 254 | 255 | CASE( "ring_span: Allows to observe the element at the back" ) 256 | { 257 | int arr[] = { 1, 2, 3, }; ring_span rs( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr) ); 258 | 259 | EXPECT( rs.back() == arr[dim(arr) - 1] ); 260 | } 261 | 262 | CASE( "ring_span: Allows to obtain and remove the element at the front" ) 263 | { 264 | int arr[] = { 1, 2, 3, }; ring_span rs( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr) ); 265 | 266 | EXPECT( rs.pop_front() == arr[0] ); 267 | } 268 | 269 | CASE( "ring_span: Allows to obtain and remove the element at the back" " [extension]" ) 270 | { 271 | #if nsrs_CONFIG_STRICT_P0059 272 | EXPECT( !!"pop_back() is not available (SG14)" ); 273 | #else 274 | int arr[] = { 1, 2, 3, }; ring_span rs( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr) ); 275 | 276 | EXPECT( rs.pop_back() == arr[dim(arr) - 1] ); 277 | #endif 278 | } 279 | 280 | CASE( "ring_span: Allows to copy-insert an element at the front" " [extension]" ) 281 | { 282 | #if nsrs_CONFIG_STRICT_P0059 283 | EXPECT( !!"push_front() is not available (SG14)" ); 284 | #else 285 | int arr[] = { 1, 2, 3, }; ring_span rs( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr) ); 286 | int new_element = 7; 287 | 288 | rs.push_front( new_element ); 289 | 290 | EXPECT( rs.front() == new_element ); 291 | #endif 292 | } 293 | 294 | CASE( "ring_span: Allows to move-insert an element at the front (C++11)" " [extension]" ) 295 | { 296 | #if nsrs_CPP11_OR_GREATER 297 | #if nsrs_CONFIG_STRICT_P0059 298 | EXPECT( !!"push_front() is not available (SG14)" ); 299 | #else 300 | oracle arr[3]; ring_span rs( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr) ); 301 | int value = 7; 302 | 303 | rs.push_front( oracle(value) ); 304 | 305 | EXPECT( oracle::state() == oracle::moved_from ); 306 | EXPECT( rs.front().value() == value ); 307 | #endif 308 | #else 309 | EXPECT( !!"move-semantics are not available (no C++11)" ); 310 | #endif 311 | } 312 | 313 | CASE( "ring_span: Allows to emplace an element at the front (C++11)" " [extension]" ) 314 | { 315 | #if nsrs_CPP11_OR_GREATER 316 | #if nsrs_CONFIG_STRICT_P0059 317 | EXPECT( !!"emplace_front() is not available (SG14)" ); 318 | #else 319 | SETUP("") { 320 | SECTION("of non-full ring_span") 321 | { 322 | noncopyable arr[3]; ring_span rs( &arr[0], &arr[0] + dim(arr) ); 323 | 324 | rs.emplace_front( 'a', 7 ); 325 | 326 | EXPECT( rs.front().c == 'a' ); 327 | EXPECT( rs.front().i == 7 ); 328 | } 329 | SECTION("of full ring_span") 330 | { 331 | noncopyable arr[3]; ring_span rs( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr) ); 332 | EXPECT( rs.front().c == char() ); 333 | EXPECT( rs.front().i == int() ); 334 | 335 | rs.emplace_front( 'a', 7 ); 336 | 337 | EXPECT( rs.front().c == 'a' ); 338 | EXPECT( rs.front().i == 7 ); 339 | }} 340 | #endif 341 | #else 342 | EXPECT( !!"move-semantics are not available (no C++11)" ); 343 | #endif 344 | } 345 | 346 | CASE( "ring_span: Allows to copy-insert an element at the back" ) 347 | { 348 | int arr[] = { 1, 2, 3, }; ring_span rs( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr) ); 349 | int new_element = 7; 350 | 351 | rs.push_back( new_element ); 352 | 353 | EXPECT( rs.back() == new_element ); 354 | } 355 | 356 | CASE( "ring_span: Allows to move-insert an element at the back (C++11)" ) 357 | { 358 | #if nsrs_CPP11_OR_GREATER 359 | oracle arr[3]; ring_span rs( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr) ); 360 | int value = 7; 361 | 362 | rs.push_back( oracle(value) ); 363 | 364 | EXPECT( oracle::state() == oracle::moved_from ); 365 | EXPECT( rs.back().value() == value ); 366 | #else 367 | EXPECT( !!"move-semantics are not available (no C++11)" ); 368 | #endif 369 | } 370 | 371 | CASE( "ring_span: Allows to emplace an element at the back (C++11)" ) 372 | { 373 | #if nsrs_CPP11_OR_GREATER 374 | SETUP("") { 375 | SECTION("of non-full ring_span") 376 | { 377 | noncopyable arr[3]; ring_span rs( &arr[0], &arr[0] + dim(arr) ); 378 | 379 | rs.emplace_back( 'a', 7 ); 380 | 381 | EXPECT( rs.back().c == 'a' ); 382 | EXPECT( rs.back().i == 7 ); 383 | } 384 | SECTION("of full ring_span") 385 | { 386 | noncopyable arr[3]; ring_span rs( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr) ); 387 | EXPECT( rs.back().c == char() ); 388 | EXPECT( rs.back().i == int() ); 389 | 390 | rs.emplace_back( 'a', 7 ); 391 | 392 | EXPECT( rs.back().c == 'a' ); 393 | EXPECT( rs.back().i == 7 ); 394 | }} 395 | #else 396 | EXPECT( !!"move-semantics are not available (no C++11)" ); 397 | #endif 398 | } 399 | 400 | CASE( "ring_span: Adding an element to an empty span makes it non-empty (front)" " [extension]" ) 401 | { 402 | #if nsrs_CONFIG_STRICT_P0059 403 | EXPECT( !!"push_front() is not available (SG14)" ); 404 | #else 405 | int arr[] = { 1, 2, 3, }; ring_span rs( &arr[0], &arr[0] + dim(arr) ); 406 | EXPECT( rs.empty() ); 407 | 408 | rs.push_front( 7 ); 409 | 410 | EXPECT( ! rs.empty() ); 411 | #endif 412 | } 413 | 414 | CASE( "ring_span: Adding an element to an empty span makes it non-empty (back)" ) 415 | { 416 | int arr[] = { 1, 2, 3, }; ring_span rs( &arr[0], &arr[0] + dim(arr) ); 417 | EXPECT( rs.empty() ); 418 | 419 | rs.push_back( 7 ); 420 | 421 | EXPECT( ! rs.empty() ); 422 | } 423 | 424 | CASE( "ring_span: Adding an element to an empty span doesn't change its capacity (front)" " [extension]" ) 425 | { 426 | #if nsrs_CONFIG_STRICT_P0059 427 | EXPECT( !!"push_front() is not available (SG14)" ); 428 | #else 429 | int arr[] = { 1, 2, 3, }; ring_span rs( &arr[0], &arr[0] + dim(arr) ); 430 | EXPECT( rs.empty() ); 431 | EXPECT( rs.capacity() == dim(arr) ); 432 | 433 | rs.push_front( 7 ); 434 | 435 | EXPECT( rs.capacity() == dim(arr) ); 436 | #endif 437 | } 438 | 439 | CASE( "ring_span: Adding an element to an empty span doesn't change its capacity (back)" ) 440 | { 441 | int arr[] = { 1, 2, 3, }; ring_span rs( &arr[0], &arr[0] + dim(arr) ); 442 | EXPECT( rs.empty() ); 443 | EXPECT( rs.capacity() == dim(arr) ); 444 | 445 | rs.push_back( 7 ); 446 | 447 | EXPECT( rs.capacity() == dim(arr) ); 448 | } 449 | 450 | CASE( "ring_span: Adding an element to a full span leaves it full (front)" " [extension]" ) 451 | { 452 | #if nsrs_CONFIG_STRICT_P0059 453 | EXPECT( !!"push_front() is not available (SG14)" ); 454 | #else 455 | int arr[] = { 1, 2, 3, }; ring_span rs( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr) ); 456 | EXPECT( rs.full() ); 457 | 458 | rs.push_front( 7 ); 459 | 460 | EXPECT( rs.full() ); 461 | #endif 462 | } 463 | 464 | CASE( "ring_span: Adding an element to a full span leaves it full (back)" ) 465 | { 466 | int arr[] = { 1, 2, 3, }; ring_span rs( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr) ); 467 | EXPECT( rs.full() ); 468 | 469 | rs.push_back( 7 ); 470 | 471 | EXPECT( rs.full() ); 472 | } 473 | 474 | CASE( "ring_span: Adding an element to a full span doesn't change its capacity (front)" " [extension]" ) 475 | { 476 | #if nsrs_CONFIG_STRICT_P0059 477 | EXPECT( !!"push_front() is not available (SG14)" ); 478 | #else 479 | int arr[] = { 1, 2, 3, }; ring_span rs( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr) ); 480 | EXPECT( rs.full() ); 481 | EXPECT( rs.capacity() == dim(arr) ); 482 | 483 | rs.push_front( 7 ); 484 | 485 | EXPECT( rs.capacity() == dim(arr) ); 486 | #endif 487 | } 488 | 489 | CASE( "ring_span: Adding an element to a full span doesn't change its capacity (back)" ) 490 | { 491 | int arr[] = { 1, 2, 3, }; ring_span rs( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr) ); 492 | EXPECT( rs.full() ); 493 | EXPECT( rs.capacity() == dim(arr) ); 494 | 495 | rs.push_back( 7 ); 496 | 497 | EXPECT( rs.capacity() == dim(arr) ); 498 | } 499 | 500 | CASE( "ring_span: Removing an element from an empty span asserts !empty (front)" "[.assert]" ) 501 | { 502 | int arr[] = { 1, 2, 3, }; ring_span rs( &arr[0], &arr[0] + dim(arr) ); 503 | EXPECT( rs.empty() ); 504 | 505 | (void) rs.pop_front(); 506 | } 507 | 508 | CASE( "ring_span: Removing an element from an empty span asserts !empty (back)" "[extension][.assert]" ) 509 | { 510 | #if nsrs_CONFIG_STRICT_P0059 511 | EXPECT( !!"pop_back() is not available (SG14)" ); 512 | #else 513 | int arr[] = { 1, 2, 3, }; ring_span rs( &arr[0], &arr[0] + dim(arr) ); 514 | EXPECT( rs.empty() ); 515 | 516 | (void) rs.pop_back(); 517 | #endif 518 | } 519 | 520 | CASE( "ring_span: Removing an element from a span with one element makes it empty (front)" ) 521 | { 522 | int arr[] = { 1, }; 523 | ring_span rs( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr) ); 524 | EXPECT( rs.full() ); 525 | 526 | (void) rs.pop_front(); 527 | 528 | EXPECT( rs.empty() ); 529 | } 530 | 531 | CASE( "ring_span: Removing an element from a span with one element makes it empty (back)" " [extension]" ) 532 | { 533 | #if nsrs_CONFIG_STRICT_P0059 534 | EXPECT( !!"pop_back() is not available (SG14)" ); 535 | #else 536 | int arr[] = { 1, }; 537 | ring_span rs( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr) ); 538 | EXPECT( rs.full() ); 539 | 540 | (void) rs.pop_back(); 541 | 542 | EXPECT( rs.empty() ); 543 | #endif 544 | } 545 | 546 | CASE( "ring_span: Removing an element from a span with one element doesn't change its capacity (front)" ) 547 | { 548 | int arr[] = { 1, }; 549 | ring_span rs( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr) ); 550 | EXPECT( rs.full() ); 551 | EXPECT( rs.capacity() == dim(arr) ); 552 | 553 | (void) rs.pop_front(); 554 | 555 | EXPECT( rs.capacity() == dim(arr) ); 556 | } 557 | 558 | CASE( "ring_span: Removing an element from a span with one element doesn't change its capacity (back)" " [extension]" ) 559 | { 560 | #if nsrs_CONFIG_STRICT_P0059 561 | EXPECT( !!"pop_back() is not available (SG14)" ); 562 | #else 563 | int arr[] = { 1, }; 564 | ring_span rs( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr) ); 565 | EXPECT( rs.full() ); 566 | EXPECT( rs.capacity() == dim(arr) ); 567 | 568 | (void) rs.pop_back(); 569 | 570 | EXPECT( rs.capacity() == dim(arr) ); 571 | #endif 572 | } 573 | 574 | CASE( "ring_span: Removing an element from a full span makes it not full (front)" ) 575 | { 576 | int arr[] = { 1, 2, 3, }; 577 | ring_span rs( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr) ); 578 | EXPECT( rs.full() ); 579 | 580 | (void) rs.pop_front(); 581 | 582 | EXPECT( ! rs.full() ); 583 | } 584 | 585 | CASE( "ring_span: Removing an element from a full span makes it not full (back)" " [extension]" ) 586 | { 587 | #if nsrs_CONFIG_STRICT_P0059 588 | EXPECT( !!"pop_back() is not available (SG14)" ); 589 | #else 590 | int arr[] = { 1, 2, 3, }; 591 | ring_span rs( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr) ); 592 | EXPECT( rs.full() ); 593 | 594 | (void) rs.pop_back(); 595 | 596 | EXPECT( ! rs.full() ); 597 | #endif 598 | } 599 | 600 | CASE( "ring_span: Removing an element from a full span doesn't change its capacity (front)" ) 601 | { 602 | int arr[] = { 1, 2, 3, }; 603 | ring_span rs( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr) ); 604 | EXPECT( rs.full() ); 605 | EXPECT( rs.capacity() == dim(arr) ); 606 | 607 | (void) rs.pop_front(); 608 | 609 | EXPECT( rs.capacity() == dim(arr) ); 610 | } 611 | 612 | CASE( "ring_span: Removing an element from a full span doesn't change its capacity (back)" " [extension]" ) 613 | { 614 | #if nsrs_CONFIG_STRICT_P0059 615 | EXPECT( !!"pop_back() is not available (SG14)" ); 616 | #else 617 | int arr[] = { 1, 2, 3, }; 618 | ring_span rs( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr) ); 619 | EXPECT( rs.full() ); 620 | EXPECT( rs.capacity() == dim(arr) ); 621 | 622 | (void) rs.pop_back(); 623 | 624 | EXPECT( rs.capacity() == dim(arr) ); 625 | #endif 626 | } 627 | 628 | CASE( "ring_span: Allows to swap spans (member)" ) 629 | { 630 | int arr1[] = { 1, 2, 3, }; ring_span rs1( &arr1[0], &arr1[0] + dim(arr1), &arr1[0], dim(arr1) ); 631 | int arr2[] = { 9, 8, 7, }; ring_span rs2( &arr2[0], &arr2[0] + dim(arr2), &arr2[0], dim(arr2) ); 632 | 633 | rs1.swap( rs2 ); 634 | 635 | EXPECT( tst::equal( rs1.begin(), rs1.end(), &arr2[0] ) ); 636 | EXPECT( tst::equal( rs2.begin(), rs2.end(), &arr1[0] ) ); 637 | } 638 | 639 | CASE( "ring_span: Allows to swap spans (non-member)" ) 640 | { 641 | int arr1[] = { 1, 2, 3, }; ring_span rs1( &arr1[0], &arr1[0] + dim(arr1), &arr1[0], dim(arr1) ); 642 | int arr2[] = { 9, 8, 7, }; ring_span rs2( &arr2[0], &arr2[0] + dim(arr2), &arr2[0], dim(arr2) ); 643 | 644 | using std::swap; 645 | swap( rs1, rs2 ); 646 | 647 | EXPECT( tst::equal( rs1.begin(), rs1.end(), &arr2[0] ) ); 648 | EXPECT( tst::equal( rs2.begin(), rs2.end(), &arr1[0] ) ); 649 | } 650 | 651 | CASE( "ring_span: Allows to appear in range-for (C++11)" ) 652 | { 653 | #if nsrs_CPP11_OR_GREATER 654 | int arr[] = { 1, 2, 3, }; ring_span rs( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr) ); 655 | 656 | std::vector vec; 657 | for ( auto x : rs ) 658 | { 659 | vec.push_back( x ); 660 | } 661 | 662 | EXPECT( tst::equal( vec.begin(), vec.end(), &arr[0] ) ); 663 | #else 664 | EXPECT( !!"range-for is not available (no C++11)" ); 665 | #endif 666 | } 667 | 668 | CASE( "ring_span: Allows iteration (non-const)" ) 669 | { 670 | int arr[] = { 1, 2, 3, }; 671 | ring_span rs( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr) ); 672 | ring_span const crs( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr) ); 673 | 674 | EXPECT( tst::equal( rs.begin(), rs.end(), &arr[0] ) ); 675 | EXPECT( tst::equal( crs.begin(), crs.end(), &arr[0] ) ); 676 | } 677 | 678 | CASE( "ring_span: Allows iteration (const)" ) 679 | { 680 | int arr[] = { 1, 2, 3, }; 681 | ring_span rs( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr) ); 682 | ring_span const crs( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr) ); 683 | 684 | EXPECT( tst::equal( rs.cbegin(), rs.cend(), &arr[0] ) ); 685 | EXPECT( tst::equal( crs.cbegin(), crs.cend(), &arr[0] ) ); 686 | } 687 | 688 | CASE( "ring_span: Allows iteration (mixed const-non-const)" ) 689 | { 690 | int arr[] = { 1, 2, 3, }; ring_span rs( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr) ); 691 | ring_span::iterator bgn = rs.begin(); 692 | 693 | EXPECT( bgn < rs.cend() ); 694 | EXPECT( tst::equal( rs.cbegin(), rs.cend(), bgn ) ); 695 | } 696 | 697 | CASE( "ring_span: Allows reverse iteration (non-const)" " [extension]" ) 698 | { 699 | #if nsrs_CONFIG_STRICT_P0059 700 | EXPECT( !!"rbegin(), rend() are not available (SG14)" ); 701 | #else 702 | int arr[] = { 1, 2, 3, }; 703 | ring_span rs ( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr) ); 704 | std::vector vec( &arr[0], &arr[0] + dim(arr) ); 705 | 706 | EXPECT( tst::equal( rs.rbegin(), rs.rend(), vec.rbegin() ) ); 707 | #endif 708 | } 709 | 710 | CASE( "ring_span: Allows reverse iteration (const)" " [extension]" ) 711 | { 712 | #if nsrs_CONFIG_STRICT_P0059 713 | EXPECT( !!"crbegin(), crend() are not available (SG14)" ); 714 | #else 715 | int arr[] = { 1, 2, 3, }; 716 | ring_span rs ( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr) ); 717 | std::vector vec( &arr[0], &arr[0] + dim(arr) ); 718 | 719 | EXPECT( tst::equal( rs.crbegin(), rs.crend(), vec.rbegin() ) ); 720 | #endif 721 | } 722 | 723 | CASE( "ring_span: Allows reverse iteration (mixed const-non-const)" " [extension]" ) 724 | { 725 | #if nsrs_CONFIG_STRICT_P0059 726 | EXPECT( !!"rbegin(), rend() are not available (SG14)" ); 727 | #else 728 | int arr[] = { 1, 2, 3, }; 729 | ring_span rs ( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr) ); 730 | ring_span::reverse_iterator rbgn = rs.rbegin(); 731 | 732 | EXPECT( tst::equal( rs.crbegin(), rs.crend(), rbgn ) ); 733 | #endif 734 | } 735 | 736 | CASE( "ring_span: A span with capacity zero is both empty and full" ) 737 | { 738 | int arr[] = { 1, }; ring_span rs( &arr[0], &arr[0] + 0 ); 739 | 740 | EXPECT( rs.empty() ); 741 | EXPECT( rs.full() ); 742 | } 743 | 744 | CASE( "ring_span: A full span is a delay-line of capacity elements (back-front)" ) 745 | { 746 | size_type arr[] = { 1, 2, 3, }; ring_span rs( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr) ); 747 | 748 | for ( size_type x = 4; x < 10; rs.push_back( x ), ++x ) 749 | { 750 | EXPECT( rs.pop_front() == x - rs.capacity() ); 751 | } 752 | } 753 | 754 | CASE( "ring_span: A full span is a delay-line of capacity elements (front-back)" " [extension]" ) 755 | { 756 | #if nsrs_CONFIG_STRICT_P0059 757 | EXPECT( !!"push_front(), pop_back() are not available (SG14)" ); 758 | #else 759 | size_type arr[] = { 3, 2, 1, }; ring_span rs( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr) ); 760 | 761 | for ( size_type x = 4; x < 10; rs.push_front( x ), ++x ) 762 | { 763 | EXPECT( rs.pop_back() == x - rs.capacity() ); 764 | } 765 | #endif 766 | } 767 | 768 | CASE( "ring_span: A non-full span is a stack of capacity elements (back)" " [extension]" ) 769 | { 770 | #if nsrs_CONFIG_STRICT_P0059 771 | EXPECT( !!"pop_back() is not available (SG14)" ); 772 | #else 773 | size_type arr[] = { 7, 7, 7, }; ring_span rs( &arr[0], &arr[0] + dim(arr) ); 774 | 775 | for ( size_type x = 1; x <= 3; ++x ) 776 | { 777 | rs.push_back( x ); 778 | } 779 | for ( size_type x = 3; x != 0 ; --x ) 780 | { 781 | EXPECT( x == rs.size() ); 782 | EXPECT( x == rs.pop_back() ); 783 | } 784 | #endif 785 | } 786 | 787 | CASE( "ring_span: A non-full span is a stack of capacity elements (front)" " [extension]" ) 788 | { 789 | #if nsrs_CONFIG_STRICT_P0059 790 | EXPECT( !!"push_front() is not available (SG14)" ); 791 | #else 792 | size_type arr[] = { 7, 7, 7, }; ring_span rs( &arr[0], &arr[0] + dim(arr) ); 793 | 794 | for ( size_type x = 1; x <= 3; ++x ) 795 | { 796 | rs.push_front( x ); 797 | } 798 | for ( size_type x = 3; x >= 1 ; --x ) 799 | { 800 | EXPECT( x == rs.size() ); 801 | EXPECT( x == rs.pop_front() ); 802 | } 803 | #endif 804 | } 805 | 806 | CASE( "ring_span: A non-full span behaves like an harmonica (back-front)" ) 807 | { 808 | size_type arr[] = { 7, 7, 7, }; ring_span rs( &arr[0], &arr[0] + dim(arr) ); 809 | 810 | for ( size_type x = 0; x < 3; rs.push_back( x ), ++x ) 811 | { 812 | EXPECT( x == rs.size() ); 813 | } 814 | for ( size_type x = 0; x < 3; ++x ) 815 | { 816 | EXPECT( x == 3 - rs.size() ); 817 | EXPECT( x == rs.pop_front() ); 818 | } 819 | } 820 | 821 | CASE( "ring_span: A non-full span behaves like an harmonica (front-back)" " [extension]" ) 822 | { 823 | #if nsrs_CONFIG_STRICT_P0059 824 | EXPECT( !!"push_front(), pop_back() are not available (SG14)" ); 825 | #else 826 | size_type arr[] = { 7, 7, 7, }; ring_span rs( &arr[0], &arr[0] + dim(arr) ); 827 | 828 | for ( size_type x = 0; x < 3; rs.push_front( x ), ++x ) 829 | { 830 | EXPECT( x == rs.size() ); 831 | } 832 | for ( size_type x = 0; x < 3; ++x ) 833 | { 834 | EXPECT( x == 3 - rs.size() ); 835 | EXPECT( x == rs.pop_back() ); 836 | } 837 | #endif 838 | } 839 | 840 | CASE( "ring_iterator: Allows conversion to const ring_iterator" " [extension]" ) 841 | { 842 | #if nsrs_CONFIG_STRICT_P0059 843 | EXPECT( !!"conversion to const iterator is not available (SG14)" ); 844 | #else 845 | int arr[] = { 1, 2, 3, }; ring_span rs( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr) ); 846 | ring_span::iterator bgn = rs.begin(); 847 | 848 | ring_span::const_iterator cbgn = bgn; 849 | 850 | EXPECT( tst::equal( cbgn, rs.cend(), rs.cbegin() ) ); 851 | #endif 852 | } 853 | 854 | CASE( "ring_iterator: Allows to dereference iterator (operator*())" ) 855 | { 856 | int arr[] = { 1, 2, 3, }; ring_span rs( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr) ); 857 | 858 | EXPECT( *rs.begin() == arr[0] ); 859 | } 860 | 861 | namespace op_arrow { struct S { int v; }; } 862 | 863 | CASE( "ring_iterator: Allows to dereference iterator (operator->())" ) 864 | { 865 | using op_arrow::S; 866 | 867 | S arr[] = { {1}, {2}, {3}, }; ring_span rs( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr) ); 868 | 869 | EXPECT( rs.begin()->v == arr[0].v ); 870 | } 871 | 872 | CASE( "ring_iterator: Allows to index from iterator (operator[](size_t))" ) 873 | { 874 | using op_arrow::S; 875 | 876 | S arr[] = { {1}, {2}, {3}, }; ring_span rs( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr) ); 877 | 878 | EXPECT( rs.begin()[0].v == arr[0].v ); 879 | EXPECT( rs.begin()[1].v == arr[1].v ); 880 | EXPECT( (rs.begin() + 1)[0].v == arr[1].v ); 881 | EXPECT( (rs.begin() + 1)[1].v == arr[2].v ); 882 | // explicit const iterator 883 | EXPECT( rs.cbegin()[0].v == arr[0].v ); 884 | } 885 | 886 | CASE( "ring_iterator: Allows to increment iterator (prefix)" ) 887 | { 888 | int arr[] = { 1, 2, 3, }; ring_span rs( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr) ); 889 | ring_span::iterator pos = rs.begin(); 890 | 891 | EXPECT( *++pos == arr[1] ); 892 | } 893 | 894 | CASE( "ring_iterator: Allows to increment iterator (postfix)" ) 895 | { 896 | int arr[] = { 1, 2, 3, }; ring_span rs( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr) ); 897 | ring_span::iterator pos = rs.begin(); 898 | 899 | EXPECT( *pos++ == arr[0] ); 900 | } 901 | 902 | CASE( "ring_iterator: Allows to decrement iterator (prefix)" ) 903 | { 904 | int arr[] = { 1, 2, 3, }; ring_span rs( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr) ); 905 | ring_span::iterator pos = ++rs.begin(); 906 | 907 | EXPECT( *--pos == arr[0] ); 908 | } 909 | 910 | CASE( "ring_iterator: Allows to decrement iterator (postfix)" ) 911 | { 912 | int arr[] = { 1, 2, 3, }; ring_span rs( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr) ); 913 | ring_span::iterator pos = ++rs.begin(); 914 | 915 | EXPECT( *pos-- == arr[1] ); 916 | } 917 | 918 | CASE( "ring_iterator: Allows to advance iterator (+=)" " [extension]" ) 919 | { 920 | #if nsrs_CONFIG_STRICT_P0059 921 | EXPECT( !!"iterator advancement is not implemented properly (SG14)" ); 922 | #else 923 | int arr[] = { 1, 2, 3, }; ring_span rs( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr) ); 924 | ring_span::iterator pos = rs.begin(); 925 | 926 | EXPECT( *(pos += 2) == arr[2] ); 927 | #endif 928 | } 929 | 930 | CASE( "ring_iterator: Allows to advance iterator (-=)" " [extension]" ) 931 | { 932 | #if nsrs_CONFIG_STRICT_P0059 933 | EXPECT( !!"iterator advancement is not implemented properly (SG14)" ); 934 | #else 935 | int arr[] = { 1, 2, 3, }; ring_span rs( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr) ); 936 | ring_span::iterator pos = ++rs.begin(); ++pos; 937 | 938 | EXPECT( *(pos -= 2) == arr[0] ); 939 | #endif 940 | } 941 | 942 | CASE( "ring_iterator: Allows to offset iterator (+)" " [extension]" ) 943 | { 944 | #if nsrs_CONFIG_STRICT_P0059 945 | EXPECT( !!"iterator advancement is not implemented properly (SG14)" ); 946 | #else 947 | int arr[] = { 1, 2, 3, }; ring_span rs( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr) ); 948 | ring_span::iterator pos = rs.begin(); 949 | 950 | EXPECT( *(pos + 2) == arr[2] ); 951 | EXPECT( *(2 + pos) == arr[2] ); 952 | #endif 953 | } 954 | 955 | CASE( "ring_iterator: Allows to offset iterator (-)" " [extension]" ) 956 | { 957 | #if nsrs_CONFIG_STRICT_P0059 958 | EXPECT( !!"iterator advancement is not implemented properly (SG14)" ); 959 | #else 960 | int arr[] = { 1, 2, 3, }; ring_span rs( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr) ); 961 | ring_span::iterator pos = ++rs.begin(); ++pos; 962 | 963 | EXPECT( *(pos - 2) == arr[0] ); 964 | #endif 965 | } 966 | 967 | CASE( "ring_iterator: Allows to obtain difference of iterators" " [extension]" ) 968 | { 969 | #if nsrs_CONFIG_STRICT_P0059 970 | EXPECT( !!"iterator difference is not available (SG14)" ); 971 | #else 972 | int arr[] = { 1, 2, 3, }; ring_span rs( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr) ); 973 | 974 | EXPECT( rs.end() - rs.begin() == difference_type( dim(arr) ) ); 975 | #endif 976 | } 977 | 978 | CASE( "ring_iterator: Allows to compare iterators (==)" ) 979 | { 980 | int arr[] = { 1, 2, 3, }; ring_span rs( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr) ); 981 | 982 | EXPECT( rs.begin() == rs.begin() ); 983 | EXPECT( rs.cbegin() == rs.cbegin() ); 984 | 985 | #if nsrs_CONFIG_STRICT_P0059 986 | EXPECT( !!"rbegin(), rend() are not available (SG14)" ); 987 | #else 988 | EXPECT( rs.rbegin() == rs.rbegin() ); 989 | EXPECT( rs.crbegin() == rs.crbegin() ); 990 | #endif 991 | } 992 | 993 | CASE( "ring_iterator: Allows to compare iterators (!=)" ) 994 | { 995 | int arr[] = { 1, 2, 3, }; ring_span rs( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr) ); 996 | 997 | EXPECT( rs.begin() != rs.end() ); 998 | EXPECT( rs.cbegin() != rs.cend() ); 999 | 1000 | #if nsrs_CONFIG_STRICT_P0059 1001 | EXPECT( !!"rbegin(), rend() are not available (SG14)" ); 1002 | #else 1003 | EXPECT( rs.rbegin() != rs.rend() ); 1004 | EXPECT( rs.crbegin() != rs.crend() ); 1005 | #endif 1006 | } 1007 | 1008 | CASE( "ring_iterator: Allows to compare iterators (<)" ) 1009 | { 1010 | int arr[] = { 1, 2, 3, }; ring_span rs( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr) ); 1011 | 1012 | EXPECT( rs.begin() < rs.end() ); 1013 | EXPECT( rs.cbegin() < rs.cend() ); 1014 | 1015 | #if nsrs_CONFIG_STRICT_P0059 1016 | EXPECT( !!"rbegin(), rend() are not available (SG14)" ); 1017 | #else 1018 | EXPECT( rs.rbegin() < rs.rend() ); 1019 | EXPECT( rs.crbegin() < rs.crend() ); 1020 | #endif 1021 | } 1022 | 1023 | CASE( "ring_iterator: Allows to compare iterators (<=)" ) 1024 | { 1025 | int arr[] = { 1, 2, 3, }; ring_span rs( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr) ); 1026 | 1027 | EXPECT( rs.begin() <= rs.end() ); 1028 | EXPECT( rs.begin() <= rs.begin() ); 1029 | EXPECT( rs.cbegin() <= rs.cend() ); 1030 | EXPECT( rs.cbegin() <= rs.cbegin() ); 1031 | 1032 | #if nsrs_CONFIG_STRICT_P0059 1033 | EXPECT( !!"rbegin(), rend() are not available (SG14)" ); 1034 | #else 1035 | EXPECT( rs.rbegin() <= rs.rend() ); 1036 | EXPECT( rs.rbegin() <= rs.rbegin() ); 1037 | EXPECT( rs.crbegin() <= rs.crend() ); 1038 | EXPECT( rs.crbegin() <= rs.crbegin() ); 1039 | #endif 1040 | } 1041 | 1042 | CASE( "ring_iterator: Allows to compare iterators (>)" ) 1043 | { 1044 | int arr[] = { 1, 2, 3, }; ring_span rs( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr) ); 1045 | 1046 | EXPECT( rs.end() > rs.begin() ); 1047 | EXPECT( rs.cend() > rs.cbegin() ); 1048 | 1049 | #if nsrs_CONFIG_STRICT_P0059 1050 | EXPECT( !!"rbegin(), rend() are not available (SG14)" ); 1051 | #else 1052 | EXPECT( rs.rend() > rs.rbegin() ); 1053 | EXPECT( rs.crend() > rs.crbegin() ); 1054 | #endif 1055 | } 1056 | 1057 | CASE( "ring_iterator: Allows to compare iterators (>=)" ) 1058 | { 1059 | int arr[] = { 1, 2, 3, }; ring_span rs( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr) ); 1060 | 1061 | EXPECT( rs.end() >= rs.begin() ); 1062 | EXPECT( rs.begin() >= rs.begin() ); 1063 | EXPECT( rs.cend() >= rs.cbegin() ); 1064 | EXPECT( rs.cbegin() >= rs.cbegin() ); 1065 | 1066 | #if nsrs_CONFIG_STRICT_P0059 1067 | EXPECT( !!"rbegin(), rend() are not available (SG14)" ); 1068 | #else 1069 | EXPECT( rs.rend() >= rs.rbegin() ); 1070 | EXPECT( rs.rbegin() >= rs.rbegin() ); 1071 | EXPECT( rs.crend() >= rs.crbegin() ); 1072 | EXPECT( rs.crbegin() >= rs.crbegin() ); 1073 | #endif 1074 | } 1075 | 1076 | CASE( "ring_iterator: Allows to compare iterators (mixed const-non-const)" ) 1077 | { 1078 | int arr[] = { 1, 2, 3, }; ring_span rs( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr) ); 1079 | ring_span::iterator bgn = rs.begin(); 1080 | 1081 | EXPECT( bgn != rs.cend() ); 1082 | EXPECT( bgn < rs.cend() ); 1083 | EXPECT( bgn <= rs.cend() ); 1084 | EXPECT( rs.cend() > bgn ); 1085 | EXPECT( rs.cend() >= bgn ); 1086 | } 1087 | 1088 | CASE( "null_popper: A null popper returns void" ) 1089 | { 1090 | int arr[] = { 1, 2, 3, }; ring_span > rs( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr) ); 1091 | 1092 | rs.pop_front(); 1093 | } 1094 | 1095 | CASE( "null_popper: A null popper leaves the original element unchanged" ) 1096 | { 1097 | int arr[] = { 1, 2, 3, }; ring_span > rs( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr) ); 1098 | 1099 | rs.pop_front(); 1100 | 1101 | EXPECT( arr[0] == 1 ); 1102 | } 1103 | 1104 | CASE( "default_popper: A default popper returns the element" ) 1105 | { 1106 | int arr[] = { 1, 2, 3, }; ring_span > rs( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr) ); 1107 | 1108 | EXPECT( rs.pop_front() == arr[0] ); 1109 | } 1110 | 1111 | CASE( "default_popper: A default popper moves the element (C++11)" ) 1112 | { 1113 | #if nsrs_CPP11_OR_GREATER 1114 | oracle arr[1]; ring_span > rs( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr) ); 1115 | EXPECT( oracle::state() == oracle::init ); 1116 | 1117 | (void) rs.pop_front(); 1118 | 1119 | EXPECT( oracle::state() == oracle::moved_from ); 1120 | #else 1121 | EXPECT( !!"move-semantics are not available (no C++11)" ); 1122 | #endif 1123 | } 1124 | 1125 | CASE( "default_popper: A default popper leaves the original element unchanged" ) 1126 | { 1127 | int arr[] = { 1, 2, 3, }; ring_span > rs( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr) ); 1128 | 1129 | (void) rs.pop_front(); 1130 | 1131 | EXPECT( arr[0] == 1 ); 1132 | } 1133 | 1134 | CASE( "copy_popper: A copy popper returns the element" ) 1135 | { 1136 | #if nsrs_CONFIG_STRICT_P0059 1137 | int arr[] = { 1, 2, 3, }; ring_span > rs( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr), copy_popper(7) ); 1138 | #else 1139 | int replacement = 7; 1140 | int arr[] = { 1, 2, 3, }; ring_span > rs( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr), copy_popper(replacement) ); 1141 | #endif 1142 | int result = rs.pop_front() ; 1143 | 1144 | EXPECT( result == 1 ); 1145 | 1146 | } 1147 | 1148 | CASE( "copy_popper: A copy popper replaces the original element" ) 1149 | { 1150 | #if nsrs_CONFIG_STRICT_P0059 1151 | int arr[] = { 1, 2, 3, }; ring_span > rs( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr), copy_popper(7) ); 1152 | 1153 | (void) rs.pop_front() ; 1154 | 1155 | EXPECT( arr[0] == 7 ); 1156 | #else 1157 | int replacement = 7; 1158 | int arr[] = { 1, 2, 3, }; ring_span > rs( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr), copy_popper(replacement) ); 1159 | 1160 | (void) rs.pop_front() ; 1161 | 1162 | EXPECT( arr[0] == replacement ); 1163 | #endif 1164 | } 1165 | 1166 | // ring: 1167 | 1168 | #include 1169 | 1170 | CASE( "ring: Allows to create data owning ring from container" ) 1171 | { 1172 | ring< std::vector > r( 3 ); 1173 | 1174 | EXPECT( r.size() == 0u ); 1175 | EXPECT( r.capacity() == 3u ); 1176 | 1177 | // overflow ring by one element: 1178 | 1179 | for ( size_t i = 0; i < r.size() + 1; ++i ) 1180 | { 1181 | r.push_back( static_cast( i ) ); 1182 | } 1183 | 1184 | EXPECT( r.size() == 3u ); 1185 | EXPECT( r.capacity() == 3u ); 1186 | 1187 | EXPECT( r.front() == 1 ); 1188 | EXPECT( r.back() == 3 ); 1189 | #if nsrs_RING_SPAN_LITE_EXTENSION 1190 | EXPECT( r[1] == 2 ); 1191 | #endif 1192 | 1193 | EXPECT( r.pop_front() == 1 ); 1194 | EXPECT( r.pop_front() == 2 ); 1195 | EXPECT( r.pop_front() == 3 ); 1196 | 1197 | EXPECT( r.size() == 0u ); 1198 | 1199 | unsigned int count = 0u; 1200 | 1201 | #if nsrs_RING_SPAN_LITE_EXTENSION 1202 | ++count; 1203 | r.push_front( 42 ); 1204 | EXPECT( r.front() == 42 ); 1205 | #endif 1206 | 1207 | #if nsrs_CPP11_OR_GREATER 1208 | ++count; 1209 | r.emplace_back( 77 ); 1210 | #if nsrs_RING_SPAN_LITE_EXTENSION 1211 | ++count; 1212 | r.emplace_front( 55 ); 1213 | EXPECT( r.front() == 55 ); 1214 | #endif 1215 | EXPECT( r.back () == 77 ); 1216 | #endif 1217 | EXPECT( r.size() == count ); 1218 | } 1219 | 1220 | CASE( "ring: Allows to create data owning ring from container - capacity is power of 2" ) 1221 | { 1222 | #if nsrs_RING_SPAN_LITE_EXTENSION 1223 | ring< std::vector, true > r( 4 ); 1224 | 1225 | EXPECT( r.size() == 0u ); 1226 | EXPECT( r.capacity() == 4u ); 1227 | 1228 | // overflow ring by one element: 1229 | 1230 | for ( size_t i = 0; i < r.size() + 1; ++i ) 1231 | { 1232 | r.push_back( static_cast( i ) ); 1233 | } 1234 | 1235 | EXPECT( r.size() == 4u ); 1236 | EXPECT( r.capacity() == 4u ); 1237 | 1238 | EXPECT( r.front() == 1 ); 1239 | EXPECT( r.back() == 4 ); 1240 | EXPECT( r[1] == 2 ); 1241 | 1242 | EXPECT( r.pop_front() == 1 ); 1243 | EXPECT( r.pop_front() == 2 ); 1244 | EXPECT( r.pop_front() == 3 ); 1245 | EXPECT( r.pop_front() == 4 ); 1246 | 1247 | EXPECT( r.size() == 0u ); 1248 | 1249 | r.push_front( 42 ); 1250 | EXPECT( r.front() == 42 ); 1251 | 1252 | #if nsrs_CPP11_OR_GREATER 1253 | r.emplace_front( 55 ); 1254 | r.emplace_back( 77 ); 1255 | EXPECT( r.front() == 55 ); 1256 | EXPECT( r.back () == 77 ); 1257 | 1258 | EXPECT( r.size() == 3u ); 1259 | #endif 1260 | #else 1261 | EXPECT( !!"'size is power of 2' is not available (nsrs_CONFIG_STRICT_P0059)" ); 1262 | #endif 1263 | } 1264 | 1265 | // issue-33: std::array 1266 | 1267 | CASE( "ring: Allows to create data owning ring from std::array (C++11)" ) 1268 | { 1269 | #if nsrs_CPP11_OR_GREATER 1270 | ring< std::array> r; 1271 | 1272 | EXPECT( r.size() == 0u ); 1273 | EXPECT( r.capacity() == 3u ); 1274 | 1275 | // overflow ring by one element: 1276 | 1277 | for ( size_t i = 0; i < r.size() + 1; ++i ) 1278 | { 1279 | r.push_back( static_cast( i ) ); 1280 | } 1281 | 1282 | EXPECT( r.size() == 3u ); 1283 | EXPECT( r.capacity() == 3u ); 1284 | 1285 | EXPECT( r.front() == 1 ); 1286 | EXPECT( r.back() == 3 ); 1287 | #if nsrs_RING_SPAN_LITE_EXTENSION 1288 | EXPECT( r[1] == 2 ); 1289 | #endif 1290 | 1291 | EXPECT( r.pop_front() == 1 ); 1292 | EXPECT( r.pop_front() == 2 ); 1293 | EXPECT( r.pop_front() == 3 ); 1294 | 1295 | EXPECT( r.size() == 0u ); 1296 | 1297 | unsigned int count = 0u; 1298 | 1299 | #if nsrs_RING_SPAN_LITE_EXTENSION 1300 | ++count; 1301 | r.push_front( 42 ); 1302 | EXPECT( r.front() == 42 ); 1303 | #endif 1304 | 1305 | #if nsrs_CPP11_OR_GREATER 1306 | ++count; 1307 | r.emplace_back( 77 ); 1308 | #if nsrs_RING_SPAN_LITE_EXTENSION 1309 | ++count; 1310 | r.emplace_front( 55 ); 1311 | EXPECT( r.front() == 55 ); 1312 | #endif 1313 | EXPECT( r.back () == 77 ); 1314 | #endif 1315 | EXPECT( r.size() == count ); 1316 | #else 1317 | EXPECT( !!"std::array is not available (no C++11)" ); 1318 | #endif 1319 | } 1320 | 1321 | // issue-33: C-array 1322 | 1323 | CASE( "ring: Allows to create data owning ring from C-array" ) 1324 | { 1325 | ring< int[3] > r; 1326 | 1327 | EXPECT( r.size() == 0u ); 1328 | EXPECT( r.capacity() == 3u ); 1329 | 1330 | // overflow ring by one element: 1331 | 1332 | for ( size_t i = 0; i < r.size() + 1; ++i ) 1333 | { 1334 | r.push_back( static_cast( i ) ); 1335 | } 1336 | 1337 | EXPECT( r.size() == 3u ); 1338 | EXPECT( r.capacity() == 3u ); 1339 | 1340 | EXPECT( r.front() == 1 ); 1341 | EXPECT( r.back() == 3 ); 1342 | #if nsrs_RING_SPAN_LITE_EXTENSION 1343 | EXPECT( r[1] == 2 ); 1344 | #endif 1345 | 1346 | EXPECT( r.pop_front() == 1 ); 1347 | EXPECT( r.pop_front() == 2 ); 1348 | EXPECT( r.pop_front() == 3 ); 1349 | 1350 | EXPECT( r.size() == 0u ); 1351 | 1352 | unsigned int count = 0u; 1353 | 1354 | #if nsrs_RING_SPAN_LITE_EXTENSION 1355 | ++count; 1356 | r.push_front( 42 ); 1357 | EXPECT( r.front() == 42 ); 1358 | #endif 1359 | 1360 | #if nsrs_CPP11_OR_GREATER 1361 | ++count; 1362 | r.emplace_back( 77 ); 1363 | #if nsrs_RING_SPAN_LITE_EXTENSION 1364 | ++count; 1365 | r.emplace_front( 55 ); 1366 | EXPECT( r.front() == 55 ); 1367 | #endif 1368 | EXPECT( r.back () == 77 ); 1369 | #endif 1370 | EXPECT( r.size() == count ); 1371 | } 1372 | 1373 | CASE( "tweak header: reads tweak header if supported " "[tweak]" ) 1374 | { 1375 | #if nsrs_HAVE_TWEAK_HEADER 1376 | EXPECT( RING_SPAN_TWEAK_VALUE == 42 ); 1377 | #else 1378 | EXPECT( !!"Tweak header is not available (nsrs_HAVE_TWEAK_HEADER: 0)." ); 1379 | #endif 1380 | } 1381 | 1382 | //------------------------------------------------------------------------ 1383 | // Issues: 1384 | 1385 | //------------------------------------------------------------------------ 1386 | // Applets: 1387 | 1388 | #include 1389 | 1390 | CASE( "ring_span: filter" "[.applet]" ) 1391 | { 1392 | double arr[] = { 2.0 , 3.0, 5.0, }; 1393 | double coeff[] = { 0.25, 0.5, 0.25 }; 1394 | 1395 | ring_span buffer( &arr[0], &arr[0] + dim(arr), &arr[0], dim(arr) ); 1396 | 1397 | std::cout << buffer << "\n"; 1398 | 1399 | // new sample: 1400 | buffer.push_back( 7.0 ); 1401 | 1402 | std::cout << buffer << "\n"; 1403 | 1404 | double result = tst::inner_product( buffer.begin(), buffer.end(), coeff, 0.0 ); 1405 | 1406 | std::cout << "filter result: " << result << "\n"; 1407 | 1408 | EXPECT( result == lest::approx(5.0) ); 1409 | } 1410 | 1411 | // end of file 1412 | -------------------------------------------------------------------------------- /test/t-sg14.bat: -------------------------------------------------------------------------------- 1 | cl -W3 -EHsc -Dlest_FEATURE_COLOURISE=0 -I../include -Dnsrs_CONFIG_STRICT_P0059 -Dnsrs_RING_SPAN_LITE_T_HEADER=\"ring-span-sg14.t.hpp\" ring-span-main.t.cpp ring-span.t.cpp && ring-span-main.t.exe 2 | -------------------------------------------------------------------------------- /test/t.bat: -------------------------------------------------------------------------------- 1 | @echo off & setlocal enableextensions enabledelayedexpansion 2 | :: 3 | :: t.bat - compile & run tests (MSVC). 4 | :: 5 | 6 | set unit=ring_span 7 | set unit_file=ring-span 8 | 9 | :: if no std is given, use compiler default 10 | 11 | set std=%1 12 | if not "%std%"=="" set std=-std:%std% 13 | 14 | call :CompilerVersion version 15 | echo VC%version%: %args% 16 | 17 | set UCAP=%unit% 18 | call :toupper UCAP 19 | 20 | set unit_select=-D%unit%_CONFIG_SELECT_%UCAP%=%unit%_%UCAP%_DEFAULT 21 | ::set unit_select=-D%unit%_CONFIG_SELECT_%UCAP%=%unit%_%UCAP%_NONSTD 22 | ::set unit_select=-D%unit%_CONFIG_SELECT_%UCAP%=%unit%_%UCAP%_STD 23 | 24 | set unit_config=^ 25 | -Dnsrs_CONFIG_STRICT_P0059=0 ^ 26 | -Dnsrs_CONFIG_POPPER_EMPTY_BASE_CLASS=0 27 | 28 | set msvc_defines=^ 29 | -D_CRT_SECURE_NO_WARNINGS ^ 30 | -D_SCL_SECURE_NO_WARNINGS 31 | 32 | set CppCoreCheckInclude=%VCINSTALLDIR%\Auxiliary\VS\include 33 | 34 | cl -nologo -W3 -EHsc %std% %unit_select% %unit_config% %msvc_defines% -I"%CppCoreCheckInclude%" -Ilest -I../include -I. %unit_file%-main.t.cpp %unit_file%.t.cpp && %unit_file%-main.t.exe 35 | endlocal & goto :EOF 36 | 37 | :: subroutines: 38 | 39 | :CompilerVersion version 40 | @echo off & setlocal enableextensions 41 | set tmpprogram=_getcompilerversion.tmp 42 | set tmpsource=%tmpprogram%.c 43 | 44 | echo #include ^ >%tmpsource% 45 | echo int main(){printf("%%d\n",_MSC_VER);} >>%tmpsource% 46 | 47 | cl /nologo %tmpsource% >nul 48 | for /f %%x in ('%tmpprogram%') do set version=%%x 49 | del %tmpprogram%.* >nul 50 | set offset=0 51 | if %version% LSS 1900 set /a offset=1 52 | set /a version="version / 10 - 10 * ( 5 + offset )" 53 | endlocal & set %1=%version%& goto :EOF 54 | 55 | :: toupper; makes use of the fact that string 56 | :: replacement (via SET) is not case sensitive 57 | :toupper 58 | for %%L IN (A B C D E F G H I J K L M N O P Q R S T U V W X Y Z) DO SET %1=!%1:%%L=%%L! 59 | goto :EOF 60 | -------------------------------------------------------------------------------- /test/tc-cl.bat: -------------------------------------------------------------------------------- 1 | @echo off & setlocal enableextensions enabledelayedexpansion 2 | :: 3 | :: tc-cl.bat - compile & run tests (clang-cl). 4 | :: 5 | 6 | set unit=ring_span 7 | set unit_file=ring-span 8 | 9 | :: if no std is given, use c++14 10 | 11 | set std=c++14 12 | if NOT "%1" == "" set std=%1 & shift 13 | 14 | set UCAP=%unit% 15 | call :toupper UCAP 16 | 17 | set unit_select=%unit%_%UCAP%_NONSTD 18 | ::set unit_select=%unit%_CONFIG_SELECT_%UCAP%_NONSTD 19 | if NOT "%1" == "" set unit_select=%1 & shift 20 | 21 | set args=%1 %2 %3 %4 %5 %6 %7 %8 %9 22 | 23 | set clang=clang-cl 24 | 25 | call :CompilerVersion version 26 | echo %clang% %version%: %std% %unit_select% %args% 27 | 28 | set unit_config=^ 29 | -Dnsrs_CONFIG_STRICT_P0059=0 ^ 30 | -Dnsrs_CONFIG_POPPER_EMPTY_BASE_CLASS=0 ^ 31 | -D%unit%_%UCAP%_HEADER=\"nonstd/%unit%.hpp\" ^ 32 | -D%unit%_TEST_NODISCARD=0 ^ 33 | -D%unit%_CONFIG_SELECT_%UCAP%=%unit_select% 34 | 35 | rem -flto / -fwhole-program 36 | set optflags=-O2 37 | set warnflags=-Wall -Wextra -Wpedantic -Weverything -Wshadow -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-padded -Wno-missing-noreturn -Wno-documentation-unknown-command -Wno-documentation-deprecated-sync -Wno-documentation -Wno-weak-vtables -Wno-missing-prototypes -Wno-missing-variable-declarations -Wno-exit-time-destructors -Wno-global-constructors -Wno-sign-conversion -Wno-sign-compare -Wno-implicit-int-conversion -Wno-deprecated-declarations -Wno-date-time 38 | 39 | "%clang%" -EHsc -std:%std% %optflags% %warnflags% %unit_config% -fms-compatibility-version=19.00 /imsvc lest -I../include -I. -Ics_string -I. -o %unit_file%-main.t.exe %unit_file%-main.t.cpp %unit_file%.t.cpp && %unit_file%-main.t.exe 40 | endlocal & goto :EOF 41 | 42 | :: subroutines: 43 | 44 | :CompilerVersion version 45 | echo off & setlocal enableextensions 46 | set tmpprogram=_getcompilerversion.tmp 47 | set tmpsource=%tmpprogram%.c 48 | 49 | echo #include ^ > %tmpsource% 50 | echo int main(){printf("%%d.%%d.%%d\n",__clang_major__,__clang_minor__,__clang_patchlevel__);} >> %tmpsource% 51 | 52 | "%clang%" -m32 -o %tmpprogram% %tmpsource% >nul 53 | for /f %%x in ('%tmpprogram%') do set version=%%x 54 | del %tmpprogram%.* >nul 55 | endlocal & set %1=%version%& goto :EOF 56 | 57 | :: toupper; makes use of the fact that string 58 | :: replacement (via SET) is not case sensitive 59 | :toupper 60 | for %%L IN (A B C D E F G H I J K L M N O P Q R S T U V W X Y Z) DO SET %1=!%1:%%L=%%L! 61 | goto :EOF 62 | -------------------------------------------------------------------------------- /test/tc.bat: -------------------------------------------------------------------------------- 1 | @echo off & setlocal enableextensions enabledelayedexpansion 2 | :: 3 | :: tc.bat - compile & run tests (clang). 4 | :: 5 | 6 | set unit=ring_span 7 | set unit_file=ring-span 8 | 9 | :: if no std is given, use c++14 10 | 11 | set std=%1 12 | if "%std%"=="" set std=c++14 13 | 14 | set clang=clang 15 | 16 | call :CompilerVersion version 17 | echo %clang% %version%: %std% 18 | 19 | set UCAP=%unit% 20 | call :toupper UCAP 21 | 22 | set unit_select=-D%unit%_CONFIG_SELECT_%UCAP%=%unit%_%UCAP%_DEFAULT 23 | ::set unit_select=-D%unit%_CONFIG_SELECT_%UCAP%=%unit%_%UCAP%_NONSTD 24 | ::set unit_select=-D%unit%_CONFIG_SELECT_%UCAP%=%unit%_%UCAP%_STD 25 | 26 | set unit_config=^ 27 | -Dnsrs_CONFIG_STRICT_P0059=0 ^ 28 | -Dnsrs_CONFIG_POPPER_EMPTY_BASE_CLASS=0 29 | 30 | 31 | rem -flto / -fwhole-program 32 | set optflags=-O2 33 | set warnflags=-Wall -Wextra -Wpedantic -Weverything -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-padded -Wno-missing-noreturn -Wno-documentation-unknown-command -Wno-documentation-deprecated-sync -Wno-documentation -Wno-weak-vtables -Wno-missing-prototypes -Wno-missing-variable-declarations -Wno-exit-time-destructors -Wno-global-constructors 34 | 35 | "%clang%" -m32 -std=%std% %optflags% %warnflags% %unit_select% %unit_config% -fms-compatibility-version=19.00 -isystem "%VCInstallDir%include" -isystem "%WindowsSdkDir_71A%include" -isystem lest -I../include -I. -o %unit_file%-main.t.exe %unit_file%-main.t.cpp %unit_file%.t.cpp && %unit_file%-main.t.exe 36 | endlocal & goto :EOF 37 | 38 | :: subroutines: 39 | 40 | :CompilerVersion version 41 | echo off & setlocal enableextensions 42 | set tmpprogram=_getcompilerversion.tmp 43 | set tmpsource=%tmpprogram%.c 44 | 45 | echo #include ^ > %tmpsource% 46 | echo int main(){printf("%%d.%%d.%%d\n",__clang_major__,__clang_minor__,__clang_patchlevel__);} >> %tmpsource% 47 | 48 | "%clang%" -m32 -o %tmpprogram% %tmpsource% >nul 49 | for /f %%x in ('%tmpprogram%') do set version=%%x 50 | del %tmpprogram%.* >nul 51 | endlocal & set %1=%version%& goto :EOF 52 | 53 | :: toupper; makes use of the fact that string 54 | :: replacement (via SET) is not case sensitive 55 | :toupper 56 | for %%L IN (A B C D E F G H I J K L M N O P Q R S T U V W X Y Z) DO SET %1=!%1:%%L=%%L! 57 | goto :EOF 58 | -------------------------------------------------------------------------------- /test/tg-all.bat: -------------------------------------------------------------------------------- 1 | @for %%s in ( c++98 c++03 c++11 c++14 c++17 c++20 c++23 ) do ( 2 | call tg.bat %%s 3 | ) 4 | -------------------------------------------------------------------------------- /test/tg-sg14.bat: -------------------------------------------------------------------------------- 1 | @setlocal 2 | @set std=%1 3 | @if "%std%"=="" set std=c++14 4 | g++ -std=%std% -O2 -Wall -Wextra -Wno-unused-parameter -Dlest_FEATURE_COLOURISE=0 -I../include -I. -Dnsrs_CONFIG_STRICT_P0059 -Dnsrs_RING_SPAN_LITE_T_HEADER=\"ring-span-sg14.t.hpp\" -o ring-span-main.t.exe ring-span-main.t.cpp ring-span.t.cpp && ring-span-main.t.exe 5 | @endlocal 6 | 7 | -------------------------------------------------------------------------------- /test/tg.bat: -------------------------------------------------------------------------------- 1 | @echo off & setlocal enableextensions enabledelayedexpansion 2 | :: 3 | :: tg.bat - compile & run tests (GNUC). 4 | :: 5 | 6 | set unit=ring_span 7 | set unit_file=ring-span 8 | 9 | :: if no std is given, use c++11 10 | 11 | set std=%1 12 | set args=%2 %3 %4 %5 %6 %7 %8 %9 13 | if "%1" == "" set std=c++11 14 | 15 | set gpp=g++ 16 | 17 | call :CompilerVersion version 18 | echo %gpp% %version%: %std% %args% 19 | 20 | set UCAP=%unit% 21 | call :toupper UCAP 22 | 23 | set unit_select=-D%unit%_CONFIG_SELECT_%UCAP%=%unit%_%UCAP%_DEFAULT 24 | ::set unit_select=-D%unit%_CONFIG_SELECT_%UCAP%=%unit%_%UCAP%_NONSTD 25 | ::set unit_select=-D%unit%_CONFIG_SELECT_%UCAP%=%unit%_%UCAP%_STD 26 | 27 | set unit_config=^ 28 | -Dnsrs_CONFIG_STRICT_P0059=0 ^ 29 | -Dnsrs_CONFIG_POPPER_EMPTY_BASE_CLASS=0 30 | 31 | 32 | rem -flto / -fwhole-program 33 | set optflags=-O2 34 | set warnflags=-Wall -Wextra -Wpedantic -Wconversion -Wsign-conversion -Wno-padded -Wno-missing-noreturn 35 | 36 | %gpp% -std=%std% %optflags% %warnflags% %unit_select% %unit_config% -o %unit_file%-main.t.exe -isystem lest -I../include -I. %unit_file%-main.t.cpp %unit_file%.t.cpp && %unit_file%-main.t.exe 37 | 38 | endlocal & goto :EOF 39 | 40 | :: subroutines: 41 | 42 | :CompilerVersion version 43 | echo off & setlocal enableextensions 44 | set tmpprogram=_getcompilerversion.tmp 45 | set tmpsource=%tmpprogram%.c 46 | 47 | echo #include ^ > %tmpsource% 48 | echo int main(){printf("%%d.%%d.%%d\n",__GNUC__,__GNUC_MINOR__,__GNUC_PATCHLEVEL__);} >> %tmpsource% 49 | 50 | %gpp% -o %tmpprogram% %tmpsource% >nul 51 | for /f %%x in ('%tmpprogram%') do set version=%%x 52 | del %tmpprogram%.* >nul 53 | endlocal & set %1=%version%& goto :EOF 54 | 55 | :: toupper; makes use of the fact that string 56 | :: replacement (via SET) is not case sensitive 57 | :toupper 58 | for %%L IN (A B C D E F G H I J K L M N O P Q R S T U V W X Y Z) DO SET %1=!%1:%%L=%%L! 59 | goto :EOF 60 | --------------------------------------------------------------------------------