diff --git a/.codespellignore b/.codespellignore new file mode 100644 index 0000000..e69de29 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0fb1f6a..fccb1ce 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -97,4 +97,3 @@ jobs: set -x [[ ! -z "${{ matrix.config.asan_options }}" ]] && export ASAN_OPTIONS="${{ matrix.config.asan_options }}" ctest --build-config Asan --output-on-failure --test-dir .build - diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml new file mode 100644 index 0000000..f3c4332 --- /dev/null +++ b/.github/workflows/pre-commit.yml @@ -0,0 +1,76 @@ +name: Lint Check (pre-commit) + +on: + # We have to use pull_request_target here as pull_request does not grant + # enough permission for reviewdog + pull_request_target: + push: + +jobs: + pre-commit-push: + name: Pre-Commit check on Push + runs-on: ubuntu-latest + if: ${{ github.event_name == 'push' }} + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: 3.13 + + # We wish to run pre-commit on all files instead of the changes + # only made in the push commit. + # + # So linting error persists when there's formatting problem. + - uses: pre-commit/action@v3.0.1 + + pre-commit-pr: + name: Pre-Commit check on PR + runs-on: ubuntu-latest + if: ${{ github.event_name == 'pull_request_target' }} + + permissions: + contents: read + checks: write + issues: write + pull-requests: write + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + # pull_request_target checkout the base of the repo + # We need to checkout the actual pr to lint the changes. + - name: Checkout pr + run: gh pr checkout ${{ github.event.number }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: 3.13 + + # we only lint on the changed file in PR. + - name: Get Changed Files + id: changed-files + uses: tj-actions/changed-files@v45 + + # See: + # https://github.com/tj-actions/changed-files?tab=readme-ov-file#using-local-git-directory- + - uses: pre-commit/action@v3.0.1 + id: run-pre-commit + with: + extra_args: --files ${{ steps.changed-files.outputs.all_changed_files }} + + # Review dog posts the suggested change from pre-commit to the pr. + - name: suggester / pre-commit + uses: reviewdog/action-suggester@v1 + if: ${{ failure() && steps.run-pre-commit.conclusion == 'failure' }} + with: + tool_name: pre-commit + level: warning + reviewdog_flags: "-fail-level=error" diff --git a/.gitmodules b/.gitmodules index 8b13789..e69de29 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1 +0,0 @@ - diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..64d27cf --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,40 @@ +# See https://pre-commit.com for more information +# See https://pre-commit.com/hooks.html for more hooks +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v5.0.0 + hooks: + - id: trailing-whitespace + - id: end-of-file-fixer + - id: check-yaml + - id: check-added-large-files + + # Clang-format for C++ + # This brings in a portable version of clang-format. + # See also: https://github.com/ssciwr/clang-format-wheel + - repo: https://github.com/pre-commit/mirrors-clang-format + rev: v19.1.4 + hooks: + - id: clang-format + types_or: [c++, c] + + # CMake linting and formatting + - repo: https://github.com/BlankSpruce/gersemi + rev: 0.17.1 + hooks: + - id: gersemi + name: CMake linting + + # Markdown linting + # Config file: .markdownlint.yaml + - repo: https://github.com/igorshubovych/markdownlint-cli + rev: v0.43.0 + hooks: + - id: markdownlint + + - repo: https://github.com/codespell-project/codespell + rev: v2.3.0 + hooks: + - id: codespell + files: ^.*\.(cmake|cpp|hpp|txt|md|json|in|yaml|yml)$ + args: ["--ignore-words", ".codespellignore" ] diff --git a/CMakeLists.txt b/CMakeLists.txt index 4c7aa2b..8b0d091 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,10 +5,7 @@ cmake_minimum_required(VERSION 3.27...3.31) -project( - beman.iterator_interface - VERSION 0.0.0 - LANGUAGES CXX) +project(beman.iterator_interface VERSION 0.0.0 LANGUAGES CXX) # Local helpers: required to include CompilerFeatureTest. list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") @@ -24,40 +21,49 @@ beman_iterator_check_deducing_this(COMPILER_SUPPORTS_DEDUCING_THIS) set(TARGETS_EXPORT_NAME ${CMAKE_PROJECT_NAME}Targets) option( - BEMAN_ITERATOR_INTERFACE_USE_DEDUCING_THIS - "Make use of C++23 \"deducing this\" feature (P0847R7). Turn this off for non-conforming compilers." - ${COMPILER_SUPPORTS_DEDUCING_THIS}) + BEMAN_ITERATOR_INTERFACE_USE_DEDUCING_THIS + "Make use of C++23 \"deducing this\" feature (P0847R7). Turn this off for non-conforming compilers." + ${COMPILER_SUPPORTS_DEDUCING_THIS} +) option( - BEMAN_ITERATOR_INTERFACE_BUILD_TESTS - "Enable building tests and test infrastructure. Default: ON. Values: {ON, OFF}." - ${PROJECT_IS_TOP_LEVEL}) - -option(BEMAN_ITERATOR_INTERFACE_BUILD_EXAMPLES - "Enable building examples. Default: ON. Values: {ON, OFF}." - ${PROJECT_IS_TOP_LEVEL}) - -if(BEMAN_ITERATOR_INTERFACE_USE_DEDUCING_THIS - AND NOT COMPILER_SUPPORTS_DEDUCING_THIS) - message( - WARNING - "Building with C++23 \"deducing this\" feature (P0847R7) despite of the compiler's lack of actual support for it." - ) + BEMAN_ITERATOR_INTERFACE_BUILD_TESTS + "Enable building tests and test infrastructure. Default: ON. Values: {ON, OFF}." + ${PROJECT_IS_TOP_LEVEL} +) + +option( + BEMAN_ITERATOR_INTERFACE_BUILD_EXAMPLES + "Enable building examples. Default: ON. Values: {ON, OFF}." + ${PROJECT_IS_TOP_LEVEL} +) + +if( + BEMAN_ITERATOR_INTERFACE_USE_DEDUCING_THIS + AND NOT COMPILER_SUPPORTS_DEDUCING_THIS +) + message( + WARNING + "Building with C++23 \"deducing this\" feature (P0847R7) despite of the compiler's lack of actual support for it." + ) endif() configure_file( - "${PROJECT_SOURCE_DIR}/include/beman/iterator_interface/config.hpp.in" - "${PROJECT_BINARY_DIR}/include/beman/iterator_interface/config.hpp" @ONLY) + "${PROJECT_SOURCE_DIR}/include/beman/iterator_interface/config.hpp.in" + "${PROJECT_BINARY_DIR}/include/beman/iterator_interface/config.hpp" + @ONLY +) if(BEMAN_ITERATOR_INTERFACE_BUILD_TESTS) - # Fetch GoogleTest - FetchContent_Declare( - googletest - EXCLUDE_FROM_ALL - GIT_REPOSITORY https://github.com/google/googletest.git - GIT_TAG e39786088138f2749d64e9e90e0f9902daa77c40 # release-1.15.0 - ) - FetchContent_MakeAvailable(googletest) + # Fetch GoogleTest + FetchContent_Declare( + googletest + EXCLUDE_FROM_ALL + GIT_REPOSITORY https://github.com/google/googletest.git + GIT_TAG + e39786088138f2749d64e9e90e0f9902daa77c40 # release-1.15.0 + ) + FetchContent_MakeAvailable(googletest) endif() # Create the library target and named header set for beman.iterator_interface @@ -65,35 +71,33 @@ add_library(beman.iterator_interface STATIC) add_library(beman::iterator_interface ALIAS beman.iterator_interface) target_sources( - beman.iterator_interface - PUBLIC FILE_SET - beman_iterator_interface_headers - TYPE - HEADERS - BASE_DIRS - ${PROJECT_BINARY_DIR}/include - ${PROJECT_SOURCE_DIR}/include - FILES - ${PROJECT_BINARY_DIR}/include/beman/iterator_interface/config.hpp) + beman.iterator_interface + PUBLIC + FILE_SET beman_iterator_interface_headers + TYPE HEADERS + BASE_DIRS ${PROJECT_BINARY_DIR}/include ${PROJECT_SOURCE_DIR}/include + FILES ${PROJECT_BINARY_DIR}/include/beman/iterator_interface/config.hpp +) add_subdirectory(src/beman/iterator_interface) add_subdirectory(include/beman/iterator_interface) if(BEMAN_ITERATOR_INTERFACE_BUILD_TESTS) - enable_testing() - add_subdirectory(tests/beman/iterator_interface) + enable_testing() + add_subdirectory(tests/beman/iterator_interface) endif() if(BEMAN_ITERATOR_INTERFACE_BUILD_EXAMPLES) - add_subdirectory(examples) + add_subdirectory(examples) endif() # Coverage configure_file("cmake/gcovr.cfg.in" gcovr.cfg @ONLY) add_custom_target( - process_coverage - WORKING_DIRECTORY ${CMAKE_BINARY_DIR} - COMMENT "Running gcovr to process coverage results" - COMMAND mkdir -p coverage - COMMAND gcovr --config gcovr.cfg .) + process_coverage + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + COMMENT "Running gcovr to process coverage results" + COMMAND mkdir -p coverage + COMMAND gcovr --config gcovr.cfg . +) diff --git a/README.md b/README.md index cf365bf..8e4a65c 100644 --- a/README.md +++ b/README.md @@ -18,24 +18,32 @@ Source is licensed with the Apache 2.0 license with LLVM exceptions // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -Documentation and associated papers are licensed with the Creative Commons Attribution 4.0 International license. +Documentation and associated papers are licensed with the Creative Commons +Attribution 4.0 International license. // SPDX-License-Identifier: CC-BY-4.0 -The intent is that the source and documentation are available for use by people implementing their iterator types. +The intent is that the source and documentation are available for use by people +implementing their iterator types. -The README itself is licensed with CC0 1.0 Universal. Copy the contents and incorporate in your own work as you see fit. +The README itself is licensed with CC0 1.0 Universal. Copy the contents and +incorporate in your own work as you see fit. // SPDX-License-Identifier: CC0-1.0 ## Examples -Full runnable examples can be found in `examples/` - please check [examples/README.md](./examples/README.md) for building the code on local setup or on Compiler Explorer. +Full runnable examples can be found in `examples/` - please check +[examples/README.md](./examples/README.md) for building the code on local setup +or on Compiler Explorer. ### Repeated Chars Iterator -The next code snippet shows iterator interface support added in [`std::iterator_interface` (P2727R)](https://wg21.link/P2727R4): define a random access iterator that iterates over a sequence of characters repeated indefinitely. +The next code snippet shows iterator interface support added in +[`std::iterator_interface` (P2727R)](https://wg21.link/P2727R4): define a random +access iterator that iterates over a sequence of characters repeated indefinitely. + ```cpp #include @@ -87,11 +95,16 @@ std::copy(it_first, it_last, std::back_inserter(extracted_result)); assert(extracted_result.size() == len); std::cout << extracted_result << "\n"; // Expected output at STDOUT: "foofoof" ``` + ### Filter Integer Iterator -The next code snippet shows iterator interface support added in [`std::iterator_interface` (P2727R4)](https://wg21.link/P2727R4): define a forward iterator that iterates over a sequence of integers, skipping those that do not satisfy a predicate. +The next code snippet shows iterator interface support added in +[`std::iterator_interface` (P2727R4)](https://wg21.link/P2727R4): define a +forward iterator that iterates over a sequence of integers, skipping those that +do not satisfy a predicate. + ```cpp #include @@ -116,19 +129,21 @@ while (*it) { } std::cout << "\n"; ``` + ## How to Build ### Compiler Support -This is a modern C++ project which can be compiled with the latest C++ standards (**C++20 or later**). +This is a modern C++ project which can be compiled with the latest C++ standards +(**C++20 or later**). Default build: `C++23`. Please check `etc/${compiler}-flags.cmake`. ### Dependencies -This project is mainly tested on `Ubuntu 22.04` and `Ubuntu 24.04`, but it should be as portable as CMake is. This -project has no C or C++ dependencies. +This project is mainly tested on `Ubuntu 22.04` and `Ubuntu 24.04`, but it +should be as portable as CMake is. This project has no C or C++ dependencies. Build-time dependencies: @@ -152,9 +167,11 @@ apt-get install \ #### Preset CMake Workflows -This project strives to be as normal and simple a CMake project as possible. This build workflow in particular will -work, producing a static `beman.iterator_interface` library, ready to package: +This project strives to be as normal and simple a CMake project as possible. This +build workflow in particular will work, producing a static +`beman.iterator_interface` library, ready to package: + ```shell $ cmake --workflow --preset gcc-debug $ cmake --workflow --preset gcc-release @@ -183,10 +200,12 @@ $ tree /opt/beman.iterator_interface
Build beman.iterator_interface (verbose logs - gcc-debug) + +This should build and run the tests with system GCC with the address and +undefined behavior sanitizers enabled. -This should build and run the tests with system GCC with the address and undefined behavior sanitizers enabled. - + ```shell $ cmake --workflow --preset gcc-debug Executing workflow step 1 of 3: configure preset "gcc-debug" @@ -239,10 +258,11 @@ Test project /path/to/repo/.build/gcc-debug Total Test time (real) = 0.04 sec ``` +
- +
Install beman.iterator_interface (verbose logs - gcc-release) @@ -332,8 +352,8 @@ $ tree /opt/beman.iterator_interface └── libbeman.iterator_interface.a 8 directories, 9 files - ``` +
@@ -342,6 +362,7 @@ $ tree /opt/beman.iterator_interface ##### Default Build CI current build and test flows: + ```shell # Configure. $ cmake -G "Ninja Multi-Config" \ @@ -391,8 +412,10 @@ $ tree /opt/beman.iterator_interface 8 directories, 9 files ``` +
Build beman.iterator_interface and tests (verbose logs) + ```shell # Configure build: default build production code + tests (BEMAN_ITERATOR_INTERFACE_BUILD_TESTING=ON). @@ -418,11 +441,13 @@ Test project /path/to/repo/.build Total Test time (real) = 0.67 sec ``` +
##### Skip Tests -By default, we build and run tests. You can provide `-DBEMAN_ITERATOR_INTERFACE_BUILD_TESTING=OFF` and completely disable building tests: +By default, we build and run tests. You can provide +`-DBEMAN_ITERATOR_INTERFACE_BUILD_TESTING=OFF` and completely disable building tests: ```shell # Configure. @@ -435,7 +460,8 @@ $ cmake -G "Ninja Multi-Config" \ ##### Skip Examples -By default, we build and run tests. You can provide `-DBEMAN_ITERATOR_INTERFACE_BUILD_EXAMPLES=OFF` and completely disable building tests: +By default, we build and run tests. You can provide +`-DBEMAN_ITERATOR_INTERFACE_BUILD_EXAMPLES=OFF` and completely disable building tests: ```shell # Configure. @@ -445,4 +471,3 @@ $ cmake -G "Ninja Multi-Config" \ -DBEMAN_ITERATOR_INTERFACE_BUILD_EXAMPLES=OFF \ -B .build -S . ``` - diff --git a/cmake/CompilerFeatureTest.cmake b/cmake/CompilerFeatureTest.cmake index 99bc65d..9fed1ed 100644 --- a/cmake/CompilerFeatureTest.cmake +++ b/cmake/CompilerFeatureTest.cmake @@ -10,7 +10,8 @@ include(CheckCXXSourceCompiles) # Determines if the selected C++ compiler has deducing this support. Sets # 'result_var' to whether support is detected. function(beman_iterator_check_deducing_this result_var) - check_cxx_source_compiles( " + check_cxx_source_compiles( + " // clang-specific check due to http://github.com/llvm/llvm-project/issues/113174 // MSVC-specific check due to https://developercommunity.visualstudio.com/t/10107077 #if defined(__cpp_explicit_this_parameter) @@ -26,6 +27,8 @@ function(beman_iterator_check_deducing_this result_var) #endif #endif int main(){} -" HAVE_DEDUCING_THIS ) - set(${result_var} ${HAVE_DEDUCING_THIS} PARENT_SCOPE) +" + HAVE_DEDUCING_THIS + ) + set(${result_var} ${HAVE_DEDUCING_THIS} PARENT_SCOPE) endfunction() diff --git a/etc/ci-clang-toolchain.cmake b/etc/ci-clang-toolchain.cmake index 6a6669b..ddbacd6 100755 --- a/etc/ci-clang-toolchain.cmake +++ b/etc/ci-clang-toolchain.cmake @@ -9,13 +9,41 @@ set(CMAKE_C_COMPILER clang) set(CMAKE_CXX_COMPILER clang++) set(CMAKE_CXX_FLAGS - "-std=c++20 \ + "-std=c++20 \ -Wall -Wextra \ -stdlib=libc++ -fexperimental-library" -CACHE STRING "CXX_FLAGS" FORCE) + CACHE STRING + "CXX_FLAGS" + FORCE +) -set(CMAKE_CXX_FLAGS_DEBUG "-O0 -fno-inline -g3" CACHE STRING "C++ DEBUG Flags" FORCE) -set(CMAKE_CXX_FLAGS_RELEASE "-Ofast -g0 -DNDEBUG" CACHE STRING "C++ Release Flags" FORCE) -set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O3 -g -DNDEBUG" CACHE STRING "C++ RelWithDebInfo Flags" FORCE) -set(CMAKE_CXX_FLAGS_TSAN "-O3 -g -DNDEBUG -fsanitize=thread" CACHE STRING "C++ TSAN Flags" FORCE) -set(CMAKE_CXX_FLAGS_ASAN "-O3 -g -DNDEBUG -fsanitize=address -fsanitize=undefined -fsanitize=leak" CACHE STRING "C++ ASAN Flags" FORCE) +set(CMAKE_CXX_FLAGS_DEBUG + "-O0 -fno-inline -g3" + CACHE STRING + "C++ DEBUG Flags" + FORCE +) +set(CMAKE_CXX_FLAGS_RELEASE + "-Ofast -g0 -DNDEBUG" + CACHE STRING + "C++ Release Flags" + FORCE +) +set(CMAKE_CXX_FLAGS_RELWITHDEBINFO + "-O3 -g -DNDEBUG" + CACHE STRING + "C++ RelWithDebInfo Flags" + FORCE +) +set(CMAKE_CXX_FLAGS_TSAN + "-O3 -g -DNDEBUG -fsanitize=thread" + CACHE STRING + "C++ TSAN Flags" + FORCE +) +set(CMAKE_CXX_FLAGS_ASAN + "-O3 -g -DNDEBUG -fsanitize=address -fsanitize=undefined -fsanitize=leak" + CACHE STRING + "C++ ASAN Flags" + FORCE +) diff --git a/etc/clang-flags.cmake b/etc/clang-flags.cmake index ac796a7..30bbf65 100644 --- a/etc/clang-flags.cmake +++ b/etc/clang-flags.cmake @@ -8,11 +8,39 @@ include_guard(GLOBAL) set(CMAKE_CXX_STANDARD 23) set(CMAKE_CXX_FLAGS - "-stdlib=libc++ -Wall -Wextra " -CACHE STRING "CXX_FLAGS" FORCE) + "-stdlib=libc++ -Wall -Wextra " + CACHE STRING + "CXX_FLAGS" + FORCE +) -set(CMAKE_CXX_FLAGS_DEBUG "-O0 -fno-inline -g3" CACHE STRING "C++ DEBUG Flags" FORCE) -set(CMAKE_CXX_FLAGS_RELEASE "-Ofast -g0 -DNDEBUG" CACHE STRING "C++ Release Flags" FORCE) -set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O3 -g -DNDEBUG" CACHE STRING "C++ RelWithDebInfo Flags" FORCE) -set(CMAKE_CXX_FLAGS_TSAN "-O3 -g -DNDEBUG -fsanitize=thread" CACHE STRING "C++ TSAN Flags" FORCE) -set(CMAKE_CXX_FLAGS_ASAN "-O3 -g -DNDEBUG -fsanitize=address,undefined,leak" CACHE STRING "C++ ASAN Flags" FORCE) +set(CMAKE_CXX_FLAGS_DEBUG + "-O0 -fno-inline -g3" + CACHE STRING + "C++ DEBUG Flags" + FORCE +) +set(CMAKE_CXX_FLAGS_RELEASE + "-Ofast -g0 -DNDEBUG" + CACHE STRING + "C++ Release Flags" + FORCE +) +set(CMAKE_CXX_FLAGS_RELWITHDEBINFO + "-O3 -g -DNDEBUG" + CACHE STRING + "C++ RelWithDebInfo Flags" + FORCE +) +set(CMAKE_CXX_FLAGS_TSAN + "-O3 -g -DNDEBUG -fsanitize=thread" + CACHE STRING + "C++ TSAN Flags" + FORCE +) +set(CMAKE_CXX_FLAGS_ASAN + "-O3 -g -DNDEBUG -fsanitize=address,undefined,leak" + CACHE STRING + "C++ ASAN Flags" + FORCE +) diff --git a/etc/gcc-flags.cmake b/etc/gcc-flags.cmake index 1d7bad5..e37ea9b 100644 --- a/etc/gcc-flags.cmake +++ b/etc/gcc-flags.cmake @@ -7,12 +7,35 @@ include_guard(GLOBAL) set(CMAKE_CXX_STANDARD 23) -set(CMAKE_CXX_FLAGS - "-Wall -Wextra " -CACHE STRING "CXX_FLAGS" FORCE) +set(CMAKE_CXX_FLAGS "-Wall -Wextra " CACHE STRING "CXX_FLAGS" FORCE) -set(CMAKE_CXX_FLAGS_DEBUG "-O0 -fno-inline -g3" CACHE STRING "C++ DEBUG Flags" FORCE) -set(CMAKE_CXX_FLAGS_RELEASE "-Ofast -g0 -DNDEBUG" CACHE STRING "C++ Release Flags" FORCE) -set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O3 -g -DNDEBUG" CACHE STRING "C++ RelWithDebInfo Flags" FORCE) -set(CMAKE_CXX_FLAGS_TSAN "-O3 -g -DNDEBUG -fsanitize=thread" CACHE STRING "C++ TSAN Flags" FORCE) -set(CMAKE_CXX_FLAGS_ASAN "-O3 -g -DNDEBUG -fsanitize=undefined" CACHE STRING "C++ ASAN Flags" FORCE) +set(CMAKE_CXX_FLAGS_DEBUG + "-O0 -fno-inline -g3" + CACHE STRING + "C++ DEBUG Flags" + FORCE +) +set(CMAKE_CXX_FLAGS_RELEASE + "-Ofast -g0 -DNDEBUG" + CACHE STRING + "C++ Release Flags" + FORCE +) +set(CMAKE_CXX_FLAGS_RELWITHDEBINFO + "-O3 -g -DNDEBUG" + CACHE STRING + "C++ RelWithDebInfo Flags" + FORCE +) +set(CMAKE_CXX_FLAGS_TSAN + "-O3 -g -DNDEBUG -fsanitize=thread" + CACHE STRING + "C++ TSAN Flags" + FORCE +) +set(CMAKE_CXX_FLAGS_ASAN + "-O3 -g -DNDEBUG -fsanitize=undefined" + CACHE STRING + "C++ ASAN Flags" + FORCE +) diff --git a/etc/gcc-toolchain.cmake b/etc/gcc-toolchain.cmake index 19f0850..1119311 100755 --- a/etc/gcc-toolchain.cmake +++ b/etc/gcc-toolchain.cmake @@ -9,12 +9,40 @@ set(CMAKE_C_COMPILER gcc) set(CMAKE_CXX_COMPILER g++) set(CMAKE_CXX_FLAGS - "-std=c++20 \ + "-std=c++20 \ -Wall -Wextra " -CACHE STRING "CXX_FLAGS" FORCE) + CACHE STRING + "CXX_FLAGS" + FORCE +) -set(CMAKE_CXX_FLAGS_DEBUG "-O0 -fno-inline -g3" CACHE STRING "C++ DEBUG Flags" FORCE) -set(CMAKE_CXX_FLAGS_RELEASE "-Ofast -g0 -DNDEBUG" CACHE STRING "C++ Release Flags" FORCE) -set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O3 -g -DNDEBUG" CACHE STRING "C++ RelWithDebInfo Flags" FORCE) -set(CMAKE_CXX_FLAGS_TSAN "-O3 -g -DNDEBUG -fsanitize=thread" CACHE STRING "C++ TSAN Flags" FORCE) -set(CMAKE_CXX_FLAGS_ASAN "-O3 -g -DNDEBUG -fsanitize=address,undefined,leak" CACHE STRING "C++ ASAN Flags" FORCE) +set(CMAKE_CXX_FLAGS_DEBUG + "-O0 -fno-inline -g3" + CACHE STRING + "C++ DEBUG Flags" + FORCE +) +set(CMAKE_CXX_FLAGS_RELEASE + "-Ofast -g0 -DNDEBUG" + CACHE STRING + "C++ Release Flags" + FORCE +) +set(CMAKE_CXX_FLAGS_RELWITHDEBINFO + "-O3 -g -DNDEBUG" + CACHE STRING + "C++ RelWithDebInfo Flags" + FORCE +) +set(CMAKE_CXX_FLAGS_TSAN + "-O3 -g -DNDEBUG -fsanitize=thread" + CACHE STRING + "C++ TSAN Flags" + FORCE +) +set(CMAKE_CXX_FLAGS_ASAN + "-O3 -g -DNDEBUG -fsanitize=address,undefined,leak" + CACHE STRING + "C++ ASAN Flags" + FORCE +) diff --git a/etc/llvm-16-toolchain.cmake b/etc/llvm-16-toolchain.cmake index 1651049..d25ddf1 100755 --- a/etc/llvm-16-toolchain.cmake +++ b/etc/llvm-16-toolchain.cmake @@ -9,13 +9,41 @@ set(CMAKE_C_COMPILER clang-16) set(CMAKE_CXX_COMPILER clang++-16) set(CMAKE_CXX_FLAGS - "-std=c++20 \ + "-std=c++20 \ -Wall -Wextra \ -stdlib=libc++ -fexperimental-library" -CACHE STRING "CXX_FLAGS" FORCE) + CACHE STRING + "CXX_FLAGS" + FORCE +) -set(CMAKE_CXX_FLAGS_DEBUG "-O0 -fno-inline -g3" CACHE STRING "C++ DEBUG Flags" FORCE) -set(CMAKE_CXX_FLAGS_RELEASE "-Ofast -g0 -DNDEBUG" CACHE STRING "C++ Release Flags" FORCE) -set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O3 -g -DNDEBUG" CACHE STRING "C++ RelWithDebInfo Flags" FORCE) -set(CMAKE_CXX_FLAGS_TSAN "-O3 -g -DNDEBUG -fsanitize=thread" CACHE STRING "C++ TSAN Flags" FORCE) -set(CMAKE_CXX_FLAGS_ASAN "-O3 -g -DNDEBUG -fsanitize=address -fsanitize=undefined -fsanitize=leak" CACHE STRING "C++ ASAN Flags" FORCE) +set(CMAKE_CXX_FLAGS_DEBUG + "-O0 -fno-inline -g3" + CACHE STRING + "C++ DEBUG Flags" + FORCE +) +set(CMAKE_CXX_FLAGS_RELEASE + "-Ofast -g0 -DNDEBUG" + CACHE STRING + "C++ Release Flags" + FORCE +) +set(CMAKE_CXX_FLAGS_RELWITHDEBINFO + "-O3 -g -DNDEBUG" + CACHE STRING + "C++ RelWithDebInfo Flags" + FORCE +) +set(CMAKE_CXX_FLAGS_TSAN + "-O3 -g -DNDEBUG -fsanitize=thread" + CACHE STRING + "C++ TSAN Flags" + FORCE +) +set(CMAKE_CXX_FLAGS_ASAN + "-O3 -g -DNDEBUG -fsanitize=address -fsanitize=undefined -fsanitize=leak" + CACHE STRING + "C++ ASAN Flags" + FORCE +) diff --git a/etc/llvm-master-toolchain.cmake b/etc/llvm-master-toolchain.cmake index b7a521c..beeb5cb 100644 --- a/etc/llvm-master-toolchain.cmake +++ b/etc/llvm-master-toolchain.cmake @@ -9,17 +9,48 @@ set(CMAKE_C_COMPILER ${LLVM_ROOT}/bin/clang) set(CMAKE_CXX_COMPILER ${LLVM_ROOT}/bin/clang++) set(CMAKE_CXX_FLAGS - "-std=c++2a \ + "-std=c++2a \ -Wall -Wextra \ -stdlib=libc++ " -CACHE STRING "CXX_FLAGS" FORCE) + CACHE STRING + "CXX_FLAGS" + FORCE +) set(CMAKE_EXE_LINKER_FLAGS - "-Wl,-rpath,${LLVM_ROOT}/lib" -CACHE STRING "CMAKE_EXE_LINKER_FLAGS" FORCE) + "-Wl,-rpath,${LLVM_ROOT}/lib" + CACHE STRING + "CMAKE_EXE_LINKER_FLAGS" + FORCE +) -set(CMAKE_CXX_FLAGS_DEBUG "-O0 -fno-inline -g3" CACHE STRING "C++ DEBUG Flags" FORCE) -set(CMAKE_CXX_FLAGS_RELEASE "-Ofast -g0 -DNDEBUG" CACHE STRING "C++ Release Flags" FORCE) -set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O3 -g -DNDEBUG" CACHE STRING "C++ Release Flags" FORCE) -set(CMAKE_CXX_FLAGS_TSAN "-O3 -g -DNDEBUG -fsanitize=thread" CACHE STRING "C++ TSAN Flags" FORCE) -set(CMAKE_CXX_FLAGS_ASAN "-O3 -g -DNDEBUG -fsanitize=address -fsanitize=undefined -fsanitize=leak" CACHE STRING "C++ ASAN Flags" FORCE) +set(CMAKE_CXX_FLAGS_DEBUG + "-O0 -fno-inline -g3" + CACHE STRING + "C++ DEBUG Flags" + FORCE +) +set(CMAKE_CXX_FLAGS_RELEASE + "-Ofast -g0 -DNDEBUG" + CACHE STRING + "C++ Release Flags" + FORCE +) +set(CMAKE_CXX_FLAGS_RELWITHDEBINFO + "-O3 -g -DNDEBUG" + CACHE STRING + "C++ Release Flags" + FORCE +) +set(CMAKE_CXX_FLAGS_TSAN + "-O3 -g -DNDEBUG -fsanitize=thread" + CACHE STRING + "C++ TSAN Flags" + FORCE +) +set(CMAKE_CXX_FLAGS_ASAN + "-O3 -g -DNDEBUG -fsanitize=address -fsanitize=undefined -fsanitize=leak" + CACHE STRING + "C++ ASAN Flags" + FORCE +) diff --git a/etc/llvm-toolchain.cmake b/etc/llvm-toolchain.cmake index 743d509..c41f6cf 100755 --- a/etc/llvm-toolchain.cmake +++ b/etc/llvm-toolchain.cmake @@ -9,13 +9,41 @@ set(CMAKE_C_COMPILER clang-14) set(CMAKE_CXX_COMPILER clang++-14) set(CMAKE_CXX_FLAGS - "-std=c++20 \ + "-std=c++20 \ -Wall -Wextra \ -stdlib=libstdc++ " -CACHE STRING "CXX_FLAGS" FORCE) + CACHE STRING + "CXX_FLAGS" + FORCE +) -set(CMAKE_CXX_FLAGS_DEBUG "-O0 -fno-inline -g3" CACHE STRING "C++ DEBUG Flags" FORCE) -set(CMAKE_CXX_FLAGS_RELEASE "-Ofast -g0 -DNDEBUG" CACHE STRING "C++ Release Flags" FORCE) -set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O3 -g -DNDEBUG" CACHE STRING "C++ RelWithDebInfo Flags" FORCE) -set(CMAKE_CXX_FLAGS_TSAN "-O3 -g -DNDEBUG -fsanitize=thread" CACHE STRING "C++ TSAN Flags" FORCE) -set(CMAKE_CXX_FLAGS_ASAN "-O3 -g -DNDEBUG -fsanitize=address -fsanitize=undefined -fsanitize=leak" CACHE STRING "C++ ASAN Flags" FORCE) +set(CMAKE_CXX_FLAGS_DEBUG + "-O0 -fno-inline -g3" + CACHE STRING + "C++ DEBUG Flags" + FORCE +) +set(CMAKE_CXX_FLAGS_RELEASE + "-Ofast -g0 -DNDEBUG" + CACHE STRING + "C++ Release Flags" + FORCE +) +set(CMAKE_CXX_FLAGS_RELWITHDEBINFO + "-O3 -g -DNDEBUG" + CACHE STRING + "C++ RelWithDebInfo Flags" + FORCE +) +set(CMAKE_CXX_FLAGS_TSAN + "-O3 -g -DNDEBUG -fsanitize=thread" + CACHE STRING + "C++ TSAN Flags" + FORCE +) +set(CMAKE_CXX_FLAGS_ASAN + "-O3 -g -DNDEBUG -fsanitize=address -fsanitize=undefined -fsanitize=leak" + CACHE STRING + "C++ ASAN Flags" + FORCE +) diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index b6e94e6..82cdf69 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -7,20 +7,28 @@ set(EXAMPLES filter_int_iterator repeated_chars_iterator) foreach(example ${EXAMPLES}) - # Add example executable. - add_executable(beman.iterator_interface.examples.${example} "") + # Add example executable. + add_executable(beman.iterator_interface.examples.${example} "") - # Add example source file. - target_sources(beman.iterator_interface.examples.${example} - PRIVATE ${example}.cpp) + # Add example source file. + target_sources( + beman.iterator_interface.examples.${example} + PRIVATE ${example}.cpp + ) - # Link example with the library. - target_link_libraries(beman.iterator_interface.examples.${example} - beman::iterator_interface) + # Link example with the library. + target_link_libraries( + beman.iterator_interface.examples.${example} + beman::iterator_interface + ) - # Install. - install( - TARGETS beman.iterator_interface.examples.${example} - COMPONENT beman.iterator_interface.examples - DESTINATION ${CMAKE_INSTALL_BINDIR}) + # Install. + install( + TARGETS + beman.iterator_interface.examples.${example} + COMPONENT + beman.iterator_interface.examples + DESTINATION + ${CMAKE_INSTALL_BINDIR} + ) endforeach() diff --git a/examples/README.md b/examples/README.md index b383872..0d84d4d 100644 --- a/examples/README.md +++ b/examples/README.md @@ -10,8 +10,10 @@ List of usage examples for `beman.iterator_interface`. Check basic `beman.iterator_interface` library usages: + * [P2727](https://wg21.link/P2727): local [./repeated_chars_iterator.cpp](./repeated_chars_iterator.cpp) or [repeated_chars_iterator.cpp@Compiler Explorer](https://godbolt.org/z/Yn9K15c9b) * [P2727](https://wg21.link/P2727): local [./filter_int_iterator.cpp](./filter_int_iterator.cpp) or [filter_int_iterator.cpp@Compiler Explorer](https://godbolt.org/z/q6933enqe) + ## Local Build and Run diff --git a/examples/filter_int_iterator.cpp b/examples/filter_int_iterator.cpp index a8ae97c..7a360fa 100644 --- a/examples/filter_int_iterator.cpp +++ b/examples/filter_int_iterator.cpp @@ -13,15 +13,15 @@ // filtered_int_iterator uses iterator_interface to define a forward iterator // that iterates over a sequence of integers, skipping those that do not satisfy a predicate. template -struct filtered_int_iterator - : beman::iterator_interface::ext_iterator_interface_compat, - std::forward_iterator_tag, - int> { +struct filtered_int_iterator : beman::iterator_interface::ext_iterator_interface_compat, + std::forward_iterator_tag, + int> { // Default constructor creates an end-of-range iterator. filtered_int_iterator() : m_it_begin(nullptr) {} // Constructor for the beginning of the sequence. - filtered_int_iterator(int* it_begin, int* it_end, Pred pred) : m_it_begin(it_begin), m_it_end(it_end), m_pred(std::move(pred)) { + filtered_int_iterator(int* it_begin, int* it_end, Pred pred) + : m_it_begin(it_begin), m_it_end(it_end), m_pred(std::move(pred)) { m_it_begin = std::find_if(m_it_begin, m_it_end, m_pred); } @@ -58,11 +58,11 @@ struct filtered_int_iterator int main() { // Create a filtered_int_iterator that iterates over the sequence {1, 2, 3, 4, 10, 11, 101, 200, 0}, // skipping odd numbers. 0 is not skipped, so it will be the last element in the sequence. - std::array a = {1, 2, 3, 4, 10, 11, 101, 200, 0}; + std::array a = {1, 2, 3, 4, 10, 11, 101, 200, 0}; filtered_int_iterator it{std::begin(a), std::end(a), [](int i) { return i % 2 == 0; }}; - - while (*it) { // Expected output at STDOUT: - std::cout << *it << " "; // 2 4 10 200 0 + + while (*it) { // Expected output at STDOUT: + std::cout << *it << " "; // 2 4 10 200 0 ++it; } std::cout << "\n"; diff --git a/examples/repeated_chars_iterator.cpp b/examples/repeated_chars_iterator.cpp index 5c07f76..fadc5dd 100644 --- a/examples/repeated_chars_iterator.cpp +++ b/examples/repeated_chars_iterator.cpp @@ -14,29 +14,27 @@ // repeated_chars_iterator uses iterator_interface to define a random access iterator // that iterates over a sequence of characters repeated indefinitely. class repeated_chars_iterator - : public beman::iterator_interface::ext_iterator_interface_compat { -public: + : public beman::iterator_interface:: + ext_iterator_interface_compat { + public: // Default constructor creates an end-of-range iterator. constexpr repeated_chars_iterator() : m_it_begin(nullptr), m_fixed_size(0), m_pos(0) {} - + // Constructor for the beginning of the sequence. constexpr repeated_chars_iterator(const char* it_begin, difference_type size, difference_type n) : m_it_begin(it_begin), m_fixed_size(size), m_pos(n) {} // Random access iterator requirements: - constexpr auto operator*() const { return m_it_begin[m_pos % m_fixed_size]; } + constexpr auto operator*() const { return m_it_begin[m_pos % m_fixed_size]; } constexpr repeated_chars_iterator& operator+=(std::ptrdiff_t i) { m_pos += i; return *this; } constexpr auto operator-(repeated_chars_iterator other) const { return m_pos - other.m_pos; } -private: + private: // Start of the sequence of characters. - const char* m_it_begin; + const char* m_it_begin; // Number of characters in the sequence. difference_type m_fixed_size; @@ -49,17 +47,18 @@ int main() { // Create a repeated_chars_iterator that iterates over the sequence "foo" repeated indefinitely: // "foofoofoofoofoofoo...". Will actually extract a prefix of the sequence and insert it into a std::string. constexpr const std::string_view target = "foo"; - constexpr const auto len = 7; // Number of extracted characters from the sequence. + constexpr const auto len = 7; // Number of extracted characters from the sequence. // Create iterators that go over the sequence "foofoofoofoofoofoo...". - repeated_chars_iterator it_first(target.data(), target.size(), 0); // target.size() == 3 is the length of "foo", 0 is this iterator's position. - repeated_chars_iterator it_last(target.data(), target.size(), len); // Same as above, but now the iterator's position is 7. + repeated_chars_iterator it_first( + target.data(), target.size(), 0); // target.size() == 3 is the length of "foo", 0 is this iterator's position. + repeated_chars_iterator it_last( + target.data(), target.size(), len); // Same as above, but now the iterator's position is 7. std::string extracted_result; std::copy(it_first, it_last, std::back_inserter(extracted_result)); assert(extracted_result.size() == len); - std::cout << extracted_result << "\n"; // Expected output at STDOUT: "foofoof" + std::cout << extracted_result << "\n"; // Expected output at STDOUT: "foofoof" return 0; } - diff --git a/include/beman/iterator_interface/CMakeLists.txt b/include/beman/iterator_interface/CMakeLists.txt index 697cd03..c71cc8d 100644 --- a/include/beman/iterator_interface/CMakeLists.txt +++ b/include/beman/iterator_interface/CMakeLists.txt @@ -4,18 +4,15 @@ # cmake-format: on target_sources( - beman.iterator_interface - PUBLIC - FILE_SET - beman_iterator_interface_headers - TYPE - HEADERS - BASE_DIRS - ${PROJECT_BINARY_DIR}/include - ${PROJECT_SOURCE_DIR}/include - FILES - iterator_interface.hpp - iterator_interface_access.hpp - detail/stl_interfaces/config.hpp - detail/stl_interfaces/fwd.hpp - detail/stl_interfaces/iterator_interface.hpp) + beman.iterator_interface + PUBLIC + FILE_SET beman_iterator_interface_headers + TYPE HEADERS + BASE_DIRS ${PROJECT_BINARY_DIR}/include ${PROJECT_SOURCE_DIR}/include + FILES + iterator_interface.hpp + iterator_interface_access.hpp + detail/stl_interfaces/config.hpp + detail/stl_interfaces/fwd.hpp + detail/stl_interfaces/iterator_interface.hpp +) diff --git a/include/beman/iterator_interface/detail/stl_interfaces/config.hpp b/include/beman/iterator_interface/detail/stl_interfaces/config.hpp index 7126fd2..cfc2c05 100644 --- a/include/beman/iterator_interface/detail/stl_interfaces/config.hpp +++ b/include/beman/iterator_interface/detail/stl_interfaces/config.hpp @@ -32,11 +32,13 @@ // multiple vI namespace alternatives exist. For example, some instances of // the v1 namespace may still be inline, if there is no v2 version of its // contents. -#if !BEMAN_ITERATOR_INTERFACE_DETAIL_STL_INTERFACES_USE_CONCEPTS && !BEMAN_ITERATOR_INTERFACE_DETAIL_STL_INTERFACES_USE_DEDUCED_THIS +#if !BEMAN_ITERATOR_INTERFACE_DETAIL_STL_INTERFACES_USE_CONCEPTS && \ + !BEMAN_ITERATOR_INTERFACE_DETAIL_STL_INTERFACES_USE_DEDUCED_THIS #define BEMAN_ITERATOR_INTERFACE_DETAIL_STL_INTERFACES_NAMESPACE_V1 inline namespace v1 #define BEMAN_ITERATOR_INTERFACE_DETAIL_STL_INTERFACES_NAMESPACE_V2 namespace v2 #define BEMAN_ITERATOR_INTERFACE_DETAIL_STL_INTERFACES_NAMESPACE_V3 namespace v3 -#elif BEMAN_ITERATOR_INTERFACE_DETAIL_STL_INTERFACES_USE_CONCEPTS && !BEMAN_ITERATOR_INTERFACE_DETAIL_STL_INTERFACES_USE_DEDUCED_THIS +#elif BEMAN_ITERATOR_INTERFACE_DETAIL_STL_INTERFACES_USE_CONCEPTS && \ + !BEMAN_ITERATOR_INTERFACE_DETAIL_STL_INTERFACES_USE_DEDUCED_THIS #define BEMAN_ITERATOR_INTERFACE_DETAIL_STL_INTERFACES_NAMESPACE_V1 namespace v1 #define BEMAN_ITERATOR_INTERFACE_DETAIL_STL_INTERFACES_NAMESPACE_V2 inline namespace v2 #define BEMAN_ITERATOR_INTERFACE_DETAIL_STL_INTERFACES_NAMESPACE_V3 namespace v3 diff --git a/include/beman/iterator_interface/detail/stl_interfaces/iterator_interface.hpp b/include/beman/iterator_interface/detail/stl_interfaces/iterator_interface.hpp index c4d29e7..c107a10 100644 --- a/include/beman/iterator_interface/detail/stl_interfaces/iterator_interface.hpp +++ b/include/beman/iterator_interface/detail/stl_interfaces/iterator_interface.hpp @@ -28,7 +28,8 @@ namespace stl_interfaces { this template implies a copy or move of the underlying object of type `T`. */ template -#if defined(BEMAN_ITERATOR_INTERFACE_DETAIL_STL_INTERFACES_DOXYGEN) || BEMAN_ITERATOR_INTERFACE_DETAIL_STL_INTERFACES_USE_CONCEPTS +#if defined(BEMAN_ITERATOR_INTERFACE_DETAIL_STL_INTERFACES_DOXYGEN) || \ + BEMAN_ITERATOR_INTERFACE_DETAIL_STL_INTERFACES_USE_CONCEPTS // clang-format off requires std::is_object_v #endif @@ -99,7 +100,9 @@ struct common_eq { }; template struct common_eq { - static constexpr auto call(T lhs, U rhs) { return iterator_interface_access::base(lhs) == iterator_interface_access::base(rhs); } + static constexpr auto call(T lhs, U rhs) { + return iterator_interface_access::base(lhs) == iterator_interface_access::base(rhs); + } }; template @@ -213,7 +216,7 @@ BEMAN_ITERATOR_INTERFACE_DETAIL_STL_INTERFACES_NAMESPACE_V1 { template constexpr auto operator->() const noexcept(noexcept(detail::make_pointer(*std::declval()))) - -> decltype(detail::make_pointer(*std::declval())) { + -> decltype(detail::make_pointer(*std::declval())) { return detail::make_pointer(*derived()); } @@ -249,7 +252,8 @@ BEMAN_ITERATOR_INTERFACE_DETAIL_STL_INTERFACES_NAMESPACE_V1 { } template - constexpr auto operator+=(difference_type n) noexcept(noexcept(iterator_interface_access::base(std::declval()) += n)) + constexpr auto + operator+=(difference_type n) noexcept(noexcept(iterator_interface_access::base(std::declval()) += n)) -> decltype(iterator_interface_access::base(std::declval()) += n, std::declval()) { iterator_interface_access::base(derived()) += n; return derived(); @@ -263,8 +267,8 @@ BEMAN_ITERATOR_INTERFACE_DETAIL_STL_INTERFACES_NAMESPACE_V1 { retval += i; return retval; } - friend BEMAN_ITERATOR_INTERFACE_DETAIL_STL_INTERFACES_HIDDEN_FRIEND_CONSTEXPR Derived operator+(difference_type i, - Derived it) noexcept { + friend BEMAN_ITERATOR_INTERFACE_DETAIL_STL_INTERFACES_HIDDEN_FRIEND_CONSTEXPR Derived + operator+(difference_type i, Derived it) noexcept { return it + i; } @@ -299,8 +303,10 @@ BEMAN_ITERATOR_INTERFACE_DETAIL_STL_INTERFACES_NAMESPACE_V1 { template constexpr auto operator-(D other) const - noexcept(noexcept(iterator_interface_access::base(std::declval()) - iterator_interface_access::base(other))) - -> decltype(iterator_interface_access::base(std::declval()) - iterator_interface_access::base(other)) { + noexcept(noexcept(iterator_interface_access::base(std::declval()) - + iterator_interface_access::base(other))) + -> decltype(iterator_interface_access::base(std::declval()) - + iterator_interface_access::base(other)) { return iterator_interface_access::base(derived()) - iterator_interface_access::base(other); } @@ -402,7 +408,8 @@ BEMAN_ITERATOR_INTERFACE_DETAIL_STL_INTERFACES_NAMESPACE_V1 { } // namespace stl_interfaces } // namespace beman::iterator_interface::detail -#if defined(BEMAN_ITERATOR_INTERFACE_DETAIL_STL_INTERFACES_DOXYGEN) || BEMAN_ITERATOR_INTERFACE_DETAIL_STL_INTERFACES_USE_CONCEPTS +#if defined(BEMAN_ITERATOR_INTERFACE_DETAIL_STL_INTERFACES_DOXYGEN) || \ + BEMAN_ITERATOR_INTERFACE_DETAIL_STL_INTERFACES_USE_CONCEPTS namespace beman::iterator_interface::detail { namespace stl_interfaces { @@ -727,7 +734,8 @@ BEMAN_ITERATOR_INTERFACE_DETAIL_STL_INTERFACES_NAMESPACE_V2 { #endif -#if defined(BEMAN_ITERATOR_INTERFACE_DETAIL_STL_INTERFACES_DOXYGEN) || BEMAN_ITERATOR_INTERFACE_DETAIL_STL_INTERFACES_USE_DEDUCED_THIS +#if defined(BEMAN_ITERATOR_INTERFACE_DETAIL_STL_INTERFACES_DOXYGEN) || \ + BEMAN_ITERATOR_INTERFACE_DETAIL_STL_INTERFACES_USE_DEDUCED_THIS namespace beman::iterator_interface::detail { namespace stl_interfaces { @@ -954,7 +962,7 @@ BEMAN_ITERATOR_INTERFACE_DETAIL_STL_INTERFACES_NAMESPACE_V3 { #define BEMAN_ITERATOR_INTERFACE_DETAIL_STL_INTERFACES_STATIC_ASSERT_CONCEPT(iter, concept_name) #endif -#define BEMAN_ITERATOR_INTERFACE_DETAIL_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS_IMPL( \ +#define BEMAN_ITERATOR_INTERFACE_DETAIL_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS_IMPL( \ iter, category, value_t, ref, ptr, diff_t) \ static_assert(std::is_same::value_type, value_t>::value, ""); \ static_assert(std::is_same::reference, ref>::value, ""); \ @@ -962,7 +970,7 @@ BEMAN_ITERATOR_INTERFACE_DETAIL_STL_INTERFACES_NAMESPACE_V3 { static_assert(std::is_same::difference_type, diff_t>::value, ""); #define BEMAN_ITERATOR_INTERFACE_DETAIL_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS( \ - iter, category, concept, value_type, reference, pointer, difference_type) \ + iter, category, concept, value_type, reference, pointer, difference_type) \ BEMAN_ITERATOR_INTERFACE_DETAIL_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS_IMPL( \ iter, category, value_type, reference, pointer, difference_type) #endif diff --git a/include/beman/iterator_interface/iterator_interface.hpp b/include/beman/iterator_interface/iterator_interface.hpp index 94592f0..1e5f1fc 100644 --- a/include/beman/iterator_interface/iterator_interface.hpp +++ b/include/beman/iterator_interface/iterator_interface.hpp @@ -142,31 +142,27 @@ struct iter_cat {}; template struct iter_cat { - using iterator_category = - std::conditional_t< - !std::is_reference_v, - std::input_iterator_tag, - std::conditional_t< - std::is_base_of_v, - std::random_access_iterator_tag, - std::conditional_t< - std::is_base_of_v, - std::bidirectional_iterator_tag, - std::forward_iterator_tag>>>; + using iterator_category = std::conditional_t< + !std::is_reference_v, + std::input_iterator_tag, + std::conditional_t, + std::random_access_iterator_tag, + std::conditional_t, + std::bidirectional_iterator_tag, + std::forward_iterator_tag>>>; }; } // namespace detail template class iterator_interface - : detail::iter_cat> -{ + : detail::iter_cat> { public: using iterator_concept = IteratorConcept; - using value_type = remove_const_t; - using reference = Reference; - using pointer = conditional_t, void, Pointer>; - using difference_type = DifferenceType; + using value_type = remove_const_t; + using reference = Reference; + using pointer = conditional_t, void, Pointer>; + using difference_type = DifferenceType; constexpr decltype(auto) operator*(this auto&& self) requires requires { *iterator_interface_access::base(self); } diff --git a/include/beman/iterator_interface/iterator_interface_access.hpp b/include/beman/iterator_interface/iterator_interface_access.hpp index 989b5d0..ea88d8e 100644 --- a/include/beman/iterator_interface/iterator_interface_access.hpp +++ b/include/beman/iterator_interface/iterator_interface_access.hpp @@ -21,6 +21,6 @@ struct iterator_interface_access { return d.base_reference(); } }; -} -} +} // namespace iterator_interface +} // namespace beman #endif diff --git a/src/beman/iterator_interface/CMakeLists.txt b/src/beman/iterator_interface/CMakeLists.txt index 53ab904..fbad15c 100644 --- a/src/beman/iterator_interface/CMakeLists.txt +++ b/src/beman/iterator_interface/CMakeLists.txt @@ -8,12 +8,16 @@ target_sources(beman.iterator_interface PUBLIC iterator_interface.cpp) # The library is empty -- exclude it install( - TARGETS beman.iterator_interface - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} - COMPONENT beman.iterator_interface.library - EXCLUDE_FROM_ALL) + TARGETS beman.iterator_interface + ARCHIVE + DESTINATION ${CMAKE_INSTALL_LIBDIR} + COMPONENT beman.iterator_interface.library + EXCLUDE_FROM_ALL +) install( - TARGETS beman.iterator_interface FILE_SET beman_iterator_interface_headers - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} - COMPONENT beman_iterator_interface_development) + TARGETS beman.iterator_interface + FILE_SET beman_iterator_interface_headers + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + COMPONENT beman_iterator_interface_development +) diff --git a/tests/beman/iterator_interface/CMakeLists.txt b/tests/beman/iterator_interface/CMakeLists.txt index 75b566d..14375ab 100644 --- a/tests/beman/iterator_interface/CMakeLists.txt +++ b/tests/beman/iterator_interface/CMakeLists.txt @@ -7,16 +7,20 @@ include(GoogleTest) add_executable(beman.iterator_interface.tests) -target_sources(beman.iterator_interface.tests - PRIVATE iterator_interface.test.cpp) +target_sources( + beman.iterator_interface.tests + PRIVATE iterator_interface.test.cpp +) target_sources( - beman.iterator_interface.tests - PRIVATE FILE_SET beman_iterator_interface_tests_headers TYPE HEADERS) + beman.iterator_interface.tests + PRIVATE FILE_SET beman_iterator_interface_tests_headers TYPE HEADERS +) target_link_libraries( - beman.iterator_interface.tests PRIVATE beman::iterator_interface GTest::gtest - GTest::gtest_main) + beman.iterator_interface.tests + PRIVATE beman::iterator_interface GTest::gtest GTest::gtest_main +) # [Issue #18](https://github.com/bemanproject/iterator_interface/issues/18): # Re-enable ASAN run CI/clang-19. diff --git a/tests/beman/iterator_interface/iterator_interface.test.cpp b/tests/beman/iterator_interface/iterator_interface.test.cpp index 4856420..86968f7 100644 --- a/tests/beman/iterator_interface/iterator_interface.test.cpp +++ b/tests/beman/iterator_interface/iterator_interface.test.cpp @@ -60,25 +60,25 @@ TEST(IteratorTest, TestRepeatedChars) { TEST(IteratorTest, TestDistance) { auto lambda = [&] { repeated_chars_iterator first("foo", 3, 0); // 3 is the length of "foo", 0 is this iterator's position. - repeated_chars_iterator last("foo", 3, 3); // 3 is the length of "foo", 3 is this iterator's position. + repeated_chars_iterator last("foo", 3, 3); // 3 is the length of "foo", 3 is this iterator's position. std::string result; std::copy(first, last, std::back_inserter(result)); CONSTEXPR_EXPECT_EQ(std::distance(first, last), 3); }; static_assert((lambda(), true)); - lambda(); + lambda(); } TEST(IteratorTest, TestNext) { auto lambda = [&] { repeated_chars_iterator first("foo", 3, 0); // 3 is the length of "foo", 0 is this iterator's position. - repeated_chars_iterator last("foo", 3, 3); // 3 is the length of "foo", 3 is this iterator's position. + repeated_chars_iterator last("foo", 3, 3); // 3 is the length of "foo", 3 is this iterator's position. CONSTEXPR_EXPECT_EQ(std::next(first, 3), last); }; static_assert((lambda(), true)); - lambda(); + lambda(); } TEST(IteratorTest, TestConcepts) { @@ -174,30 +174,26 @@ TEST(IteratorTest, OperatorArrow) { ASSERT_EQ(ai->f(), 3); } -struct dummy_input_iterator : - public ext_iterator_interface_compat< - dummy_input_iterator, std::input_iterator_tag, int, int const&, void, std::ptrdiff_t> { - constexpr dummy_input_iterator() { } - dummy_input_iterator(dummy_input_iterator const&) = delete; - dummy_input_iterator& operator=(dummy_input_iterator const&) = delete; - dummy_input_iterator(dummy_input_iterator&&) = default; - dummy_input_iterator& operator=(dummy_input_iterator&&) = default; - constexpr reference operator*() const { - return foo; - } - constexpr dummy_input_iterator& operator++() { - return *this; - } - constexpr void operator++(int) {} - - friend constexpr bool operator==(std::default_sentinel_t const&, - dummy_input_iterator const&) { - return true; - } - - friend beman::iterator_interface::iterator_interface_access; - - int foo = 0; +struct dummy_input_iterator : public ext_iterator_interface_compat { + constexpr dummy_input_iterator() {} + dummy_input_iterator(const dummy_input_iterator&) = delete; + dummy_input_iterator& operator=(const dummy_input_iterator&) = delete; + dummy_input_iterator(dummy_input_iterator&&) = default; + dummy_input_iterator& operator=(dummy_input_iterator&&) = default; + constexpr reference operator*() const { return foo; } + constexpr dummy_input_iterator& operator++() { return *this; } + constexpr void operator++(int) {} + + friend constexpr bool operator==(const std::default_sentinel_t&, const dummy_input_iterator&) { return true; } + + friend beman::iterator_interface::iterator_interface_access; + + int foo = 0; }; static_assert(std::input_iterator);