From e73526218e0ce7f7cedb5fe77b2f8ffdcae9cae3 Mon Sep 17 00:00:00 2001 From: Patrick Roberts Date: Wed, 29 Jan 2025 00:29:00 -0600 Subject: [PATCH] Initial commit --- .clang-format | 242 ++++++++++++ .devcontainer/Dockerfile | 19 + .devcontainer/devcontainer.json | 20 + .devcontainer/postcreate.sh | 5 + .github/CODEOWNERS | 3 + .github/workflows/ci_tests.yml | 223 ++++++++++++ .github/workflows/pre-commit.yml | 74 ++++ .gitignore | 6 + .markdownlint.yaml | 11 + .pre-commit-config.yaml | 32 ++ CMakeLists.txt | 122 +++++++ CMakePresets.json | 343 ++++++++++++++++++ LICENSE | 234 ++++++++++++ README.md | 47 +++ cmake/appleclang-toolchain.cmake | 39 ++ cmake/gnu-toolchain.cmake | 38 ++ cmake/llvm-toolchain.cmake | 38 ++ cmake/msvc-toolchain.cmake | 38 ++ include/beman/any_view/any_view.hpp | 99 +++++ include/beman/any_view/any_view_options.hpp | 113 ++++++ include/beman/any_view/config.hpp.in | 20 + include/beman/any_view/detail/concepts.hpp | 27 ++ include/beman/any_view/detail/iterator.hpp | 57 +++ include/beman/any_view/detail/type_traits.hpp | 21 ++ include/beman/any_view/range_traits.hpp | 101 ++++++ tests/beman/any_view/CMakeLists.txt | 11 + tests/beman/any_view/concepts.test.cpp | 50 +++ 27 files changed, 2033 insertions(+) create mode 100644 .clang-format create mode 100644 .devcontainer/Dockerfile create mode 100644 .devcontainer/devcontainer.json create mode 100644 .devcontainer/postcreate.sh create mode 100644 .github/CODEOWNERS create mode 100644 .github/workflows/ci_tests.yml create mode 100644 .github/workflows/pre-commit.yml create mode 100644 .gitignore create mode 100644 .markdownlint.yaml create mode 100644 .pre-commit-config.yaml create mode 100644 CMakeLists.txt create mode 100644 CMakePresets.json create mode 100644 LICENSE create mode 100644 README.md create mode 100644 cmake/appleclang-toolchain.cmake create mode 100644 cmake/gnu-toolchain.cmake create mode 100644 cmake/llvm-toolchain.cmake create mode 100644 cmake/msvc-toolchain.cmake create mode 100644 include/beman/any_view/any_view.hpp create mode 100644 include/beman/any_view/any_view_options.hpp create mode 100644 include/beman/any_view/config.hpp.in create mode 100644 include/beman/any_view/detail/concepts.hpp create mode 100644 include/beman/any_view/detail/iterator.hpp create mode 100644 include/beman/any_view/detail/type_traits.hpp create mode 100644 include/beman/any_view/range_traits.hpp create mode 100644 tests/beman/any_view/CMakeLists.txt create mode 100644 tests/beman/any_view/concepts.test.cpp diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..05baf03 --- /dev/null +++ b/.clang-format @@ -0,0 +1,242 @@ +--- +Language: Cpp +AccessModifierOffset: -2 +AlignAfterOpenBracket: Align +AlignArrayOfStructures: None +AlignConsecutiveAssignments: + Enabled: true + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + PadOperators: true +AlignConsecutiveBitFields: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + PadOperators: false +AlignConsecutiveDeclarations: + Enabled: true + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + PadOperators: true +AlignConsecutiveMacros: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + PadOperators: false +AlignConsecutiveShortCaseStatements: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCaseColons: false +AlignEscapedNewlines: Left +AlignOperands: Align +AlignTrailingComments: + Kind: Always + OverEmptyLines: 0 +AllowAllArgumentsOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortBlocksOnASingleLine: Never +AllowShortCaseLabelsOnASingleLine: false +AllowShortEnumsOnASingleLine: true +AllowShortFunctionsOnASingleLine: All +AllowShortIfStatementsOnASingleLine: Never +AllowShortLambdasOnASingleLine: All +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: Yes +AttributeMacros: + - __capability +BinPackArguments: false +BinPackParameters: false +BitFieldColonSpacing: Both +BraceWrapping: + AfterCaseLabel: false + AfterClass: false + AfterControlStatement: Never + AfterEnum: false + AfterExternBlock: false + AfterFunction: false + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + BeforeCatch: false + BeforeElse: false + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakAfterAttributes: Never +BreakAfterJavaFieldAnnotations: false +BreakArrays: true +BreakBeforeBinaryOperators: None +BreakBeforeConceptDeclarations: Always +BreakBeforeBraces: Custom +BreakBeforeInlineASMColon: OnlyMultiline +BreakBeforeTernaryOperators: true +BreakConstructorInitializers: BeforeColon +BreakInheritanceList: BeforeColon +BreakStringLiterals: true +# Please update .markdownlint.yaml if this line is to be updated +ColumnLimit: 119 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DerivePointerAlignment: false +DisableFormat: false +EmptyLineAfterAccessModifier: Never +EmptyLineBeforeAccessModifier: LogicalBlock +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: true +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +IfMacros: + - KJ_IF_MAYBE +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '^"(llvm|llvm-c|clang|clang-c)/' + Priority: 2 + SortPriority: 0 + CaseSensitive: false + - Regex: '^(<|"(gtest|isl|json)/)' + Priority: 3 + SortPriority: 0 + CaseSensitive: false + - Regex: '.*' + Priority: 1 + SortPriority: 0 + CaseSensitive: false +IncludeIsMainRegex: '$' +IncludeIsMainSourceRegex: '' +IndentAccessModifiers: false +IndentCaseBlocks: false +IndentCaseLabels: false +IndentExternBlock: AfterExternBlock +IndentGotoLabels: true +IndentPPDirectives: None +IndentRequiresClause: true +IndentWidth: 4 +IndentWrappedFunctionNames: false +InsertBraces: false +InsertNewlineAtEOF: false +InsertTrailingCommas: None +IntegerLiteralSeparator: + Binary: 0 + BinaryMinDigits: 0 + Decimal: 0 + DecimalMinDigits: 0 + Hex: 0 + HexMinDigits: 0 +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: true +KeepEmptyLinesAtEOF: false +LambdaBodyIndentation: Signature +LineEnding: DeriveLF +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBinPackProtocolList: Auto +ObjCBlockIndentWidth: 4 +ObjCBreakBeforeNestedBlockParam: true +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +PackConstructorInitializers: NextLine +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakOpenParenthesis: 0 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyIndentedWhitespace: 0 +PenaltyReturnTypeOnItsOwnLine: 60 +PointerAlignment: Left +PPIndentWidth: -1 +QualifierAlignment: Custom +QualifierOrder: + - inline + - static + - constexpr + - const + - volatile + - type +ReferenceAlignment: Pointer +ReflowComments: true +RemoveBracesLLVM: false +RemoveParentheses: Leave +RemoveSemicolon: false +RequiresClausePosition: OwnLine +RequiresExpressionIndentation: OuterScope +SeparateDefinitionBlocks: Leave +ShortNamespaceLines: 1 +SortIncludes: Never +SortJavaStaticImport: Before +SortUsingDeclarations: LexicographicNumeric +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: true +SpaceAroundPointerQualifiers: Default +SpaceBeforeAssignmentOperators: true +SpaceBeforeCaseColon: false +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeJsonColon: false +SpaceBeforeParens: ControlStatements +SpaceBeforeParensOptions: + AfterControlStatements: true + AfterForeachMacros: true + AfterFunctionDefinitionName: false + AfterFunctionDeclarationName: false + AfterIfMacros: true + AfterOverloadedOperator: false + AfterRequiresInClause: false + AfterRequiresInExpression: false + BeforeNonEmptyParentheses: false +SpaceBeforeRangeBasedForLoopColon: true +SpaceBeforeSquareBrackets: false +SpaceInEmptyBlock: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: Never +SpacesInContainerLiterals: true +SpacesInLineCommentPrefix: + Minimum: 1 + Maximum: -1 +SpacesInParens: Never +SpacesInParensOptions: + InCStyleCasts: false + InConditionalStatements: false + InEmptyParentheses: false + Other: false +SpacesInSquareBrackets: false +Standard: Auto +StatementAttributeLikeMacros: + - Q_EMIT +StatementMacros: + - Q_UNUSED + - QT_REQUIRE_VERSION +TabWidth: 8 +UseTab: Never +VerilogBreakBetweenInstancePorts: true +WhitespaceSensitiveMacros: + - STRINGIZE + - PP_STRINGIZE + - BOOST_PP_STRINGIZE + - NS_SWIFT_NAME + - CF_SWIFT_NAME +... diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 0000000..584eb2d --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +FROM mcr.microsoft.com/devcontainers/cpp:1-ubuntu-22.04 + +USER vscode + +# Install latest cmake +RUN wget -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null | gpg --dearmor - | sudo tee /usr/share/keyrings/kitware-archive-keyring.gpg >/dev/null +RUN echo 'deb [signed-by=/usr/share/keyrings/kitware-archive-keyring.gpg] https://apt.kitware.com/ubuntu/ jammy main' | sudo tee /etc/apt/sources.list.d/kitware.list >/dev/null +RUN sudo apt-get update && sudo apt-get install -y cmake + +# Install pre-commit +RUN sudo apt-get install -y python3-pip && pip3 install pre-commit + +# Avoid ASAN Stalling +# See: https://github.com/google/sanitizers/issues/1614 +# Alternative is to update to above clang-18 and gcc-13.2 +# Maybe crashing codespace??? +RUN sudo sysctl -w vm.mmap_rnd_bits=28 diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..9daf669 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +// For format details, see https://aka.ms/devcontainer.json. For config options, see the +// README at: https://github.com/devcontainers/templates/tree/main/src/cpp + +{ + "name": "Beman Project Generic Devcontainer", + "build": { + "dockerfile": "Dockerfile" + }, + "postCreateCommand": "bash .devcontainer/postcreate.sh", + "customizations": { + "vscode": { + "extensions": [ + "ms-vscode.cpptools", + "ms-vscode.cmake-tools" + ] + } + } +} diff --git a/.devcontainer/postcreate.sh b/.devcontainer/postcreate.sh new file mode 100644 index 0000000..483c9dd --- /dev/null +++ b/.devcontainer/postcreate.sh @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +# Setup pre-commit +pre-commit +pre-commit install diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..7b7b1e9 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +* @bretbrownjr @camio @dietmarkuehl @neatudarius @steve-downey @wusatosi @patrickroberts diff --git a/.github/workflows/ci_tests.yml b/.github/workflows/ci_tests.yml new file mode 100644 index 0000000..bf30a19 --- /dev/null +++ b/.github/workflows/ci_tests.yml @@ -0,0 +1,223 @@ +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +name: Continuous Integration Tests + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + workflow_dispatch: + schedule: + - cron: 30 15 * * * + +jobs: + gtest-test: + strategy: + fail-fast: false + matrix: + platform: + - description: Ubuntu GNU + os: ubuntu-latest + toolchain: cmake/gnu-toolchain.cmake + - description: Ubuntu LLVM + os: ubuntu-latest + toolchain: cmake/llvm-toolchain.cmake + - description: Windows MSVC + os: windows-latest + toolchain: cmake/msvc-toolchain.cmake + - description: Macos Appleclang + os: macos-latest + toolchain: cmake/appleclang-toolchain.cmake + cmake_args: + - description: Default + - description: MaxSan + args: -DBEMAN_BUILDSYS_SANITIZER=MaxSan + + name: "Unit: ${{ matrix.platform.description }} ${{ matrix.cmake_args.description }}" + runs-on: ${{ matrix.platform.os }} + steps: + - uses: actions/checkout@v4 + - name: Install Ninja + uses: lukka/get-cmake@latest + with: + cmakeVersion: ~3.25.0 + ninjaVersion: ^1.11.1 + - name: Setup MSVC + if: startsWith(matrix.platform.os, 'windows') + uses: TheMrMilchmann/setup-msvc-dev@v3 + with: + arch: x64 + - name: Setup Macos + if: startsWith(matrix.platform.os, 'macos') + run: sudo chmod -R 777 /opt/ + - name: Print installed softwares + shell: bash + run: | + echo "Build system:" + cmake --version + ninja --version + - name: Configure CMake + run: | + cmake -B build -S . -DCMAKE_CXX_STANDARD=20 -DCMAKE_TOOLCHAIN_FILE="${{ matrix.platform.toolchain }}" ${{ matrix.cmake_args.args }} + env: + CMAKE_GENERATOR: Ninja Multi-Config + - name: Build Release + run: | + # Portable commands only + cmake --build build --config Release --parallel --verbose + cmake --install build --config Release --prefix /opt/beman.any_view + ls -R /opt/beman.any_view + - name: Test Release + run: ctest --test-dir build --build-config Release + - name: Build Debug + run: | + # Portable commands only + cmake --build build --config Debug --parallel --verbose + cmake --install build --config Debug --prefix /opt/beman.any_view + ls -R /opt/beman.any_view + - name: Test Debug + run: ctest --test-dir build --build-config Debug + + configuration-test: + runs-on: ubuntu-latest + strategy: + matrix: + design: + - description: Enum Flags + arg: -DBEMAN_ANY_VIEW_DESIGN=FLAGS + - description: Range Traits + arg: -DBEMAN_ANY_VIEW_DESIGN=TRAITS + - description: Named Template Arguments + arg: -DBEMAN_ANY_VIEW_DESIGN=NAMED + option_name: + - description: Copyable + arg: -DBEMAN_ANY_VIEW_OPTION=COPYABLE + - description: Move-Only + arg: -DBEMAN_ANY_VIEW_OPTION=MOVE_ONLY + name: "CMake: ${{ matrix.design.description }} design with ${{ matrix.option_name.description }} option" + steps: + - uses: actions/checkout@v4 + - name: Setup build environment + uses: lukka/get-cmake@latest + with: + cmakeVersion: ~3.25.0 + ninjaVersion: ^1.11.1 + - name: Print installed softwares + run: | + cmake --version + ninja --version + - name: Configure CMake + run: | + cmake -B build -S . -DCMAKE_CXX_STANDARD=20 ${{ matrix.design.arg }} ${{ matrix.option_name.arg }} + env: + CMAKE_GENERATOR: Ninja Multi-Config + - name: Build Release + run: | + # Portable commands only + cmake --build build --config Release --parallel --verbose + cmake --install build --config Release --prefix /opt/beman.any_view + ls -R /opt/beman.any_view + - name: Build Debug + run: | + # Portable commands only + cmake --build build --config Debug --parallel --verbose + cmake --install build --config Debug --prefix /opt/beman.any_view + ls -R /opt/beman.any_view + + compiler-test: + runs-on: ubuntu-24.04 + strategy: + matrix: + compilers: + - class: GNU + version: 14 + - class: GNU + version: 13 + - class: GNU + version: 12 + - class: LLVM + version: 20 + - class: LLVM + version: 19 + - class: LLVM + version: 18 + - class: LLVM + version: 17 + name: "Compiler: ${{ matrix.compilers.class }} ${{ matrix.compilers.version }}" + steps: + - uses: actions/checkout@v4 + - name: Setup build environment + uses: lukka/get-cmake@latest + with: + cmakeVersion: ~3.25.0 + ninjaVersion: ^1.11.1 + - name: Install Compiler + id: install-compiler + run: | + if [ "${{ matrix.compilers.class }}" = "GNU" ]; then + CC=gcc-${{ matrix.compilers.version }} + CXX=g++-${{ matrix.compilers.version }} + + sudo add-apt-repository universe + sudo apt-get update + sudo apt-get install -y $CC + sudo apt-get install -y $CXX + + $CC --version + $CXX --version + else + wget https://apt.llvm.org/llvm.sh + chmod +x llvm.sh + sudo bash llvm.sh ${{ matrix.compilers.version }} + + CC=clang-${{ matrix.compilers.version }} + CXX=clang++-${{ matrix.compilers.version }} + + $CC --version + $CXX --version + fi + + echo "CC=$CC" >> "$GITHUB_OUTPUT" + echo "CXX=$CXX" >> "$GITHUB_OUTPUT" + - name: Configure CMake + run: | + cmake -B build -S . -DCMAKE_CXX_STANDARD=20 + env: + CC: ${{ steps.install-compiler.outputs.CC }} + CXX: ${{ steps.install-compiler.outputs.CXX }} + CMAKE_GENERATOR: Ninja Multi-Config + - name: Build Debug + run: | + cmake --build build --config Debug --verbose + cmake --install build --config Debug --prefix /opt/beman.any_view + find /opt/beman.any_view -type f + - name: Test Debug + run: ctest --test-dir build --build-config Debug + + create-issue-when-fault: + runs-on: ubuntu-latest + needs: [ gtest-test, configuration-test, compiler-test ] + if: failure() && github.event_name == 'schedule' + steps: + # See https://github.com/cli/cli/issues/5075 + - uses: actions/checkout@v4 + - name: Create issue + run: | + issue_num=$(gh issue list -s open -S "[SCHEDULED-BUILD] Build & Test failure" -L 1 --json number | jq 'if length == 0 then -1 else .[0].number end') + + body="**Build-and-Test Failure Report** + - **Time of Failure**: $(date -u '+%B %d, %Y, %H:%M %Z') + - **Commit**: [${{ github.sha }}](${{ github.server_url }}/${{ github.repository }}/commit/${{ github.sha }}) + - **Action Run**: [View logs](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) + + The scheduled build-and-test triggered by cron has failed. + Please investigate the logs and recent changes associated with this commit or rerun the workflow if you believe this is an error." + + if [[ $issue_num -eq -1 ]]; then + gh issue create --repo ${{ github.repository }} --title "[SCHEDULED-BUILD] Build & Test failure" --body "$body" + else + gh issue comment --repo ${{ github.repository }} $issue_num --body "$body" + fi + env: + GH_TOKEN: ${{ github.token }} diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml new file mode 100644 index 0000000..63e18fe --- /dev/null +++ b/.github/workflows/pre-commit.yml @@ -0,0 +1,74 @@ +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +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/.gitignore b/.gitignore new file mode 100644 index 0000000..d81e3d2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +/.cache +/.vscode +/compile_commands.json +/build diff --git a/.markdownlint.yaml b/.markdownlint.yaml new file mode 100644 index 0000000..a3df62b --- /dev/null +++ b/.markdownlint.yaml @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +# MD033/no-inline-html : Inline HTML : https://github.com/DavidAnson/markdownlint/blob/v0.35.0/doc/md033.md +# Disable inline html linter is needed for
+MD033: false + +# MD013/line-length : Line length : https://github.com/DavidAnson/markdownlint/blob/v0.35.0/doc/md013.md +# Conforms to .clang-format ColumnLimit +# Update the comment in .clang-format if we no-longer tie these two column limits. +MD013: + line_length: 119 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..5374869 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,32 @@ +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +# 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: v18.1.8 + hooks: + - id: clang-format + types_or: [ c++, c ] + # CMake linting and formatting +- repo: https://github.com/BlankSpruce/gersemi + rev: 0.15.1 + hooks: + - id: gersemi + name: CMake linting + # Markdown linting + # Config file: .markdownlint.yaml +- repo: https://github.com/igorshubovych/markdownlint-cli + rev: v0.42.0 + hooks: + - id: markdownlint diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..9283623 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,122 @@ +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required(VERSION 3.25) + +project( + beman.any_view + DESCRIPTION "A generalized type-erased view with customizable properties" + LANGUAGES CXX) + +# [CMAKE.SKIP_TESTS] +option( + BEMAN_ANY_VIEW_BUILD_TESTS + "Enable building tests and test infrastructure. Default: ON. Values: { ON, OFF }." + ${PROJECT_IS_TOP_LEVEL}) + +# [CPP.NO_FLAG_FORKING] +set(BEMAN_ANY_VIEW_DESIGN + "FLAGS" + CACHE + STRING + "Enable alternative design for any_view_options. Default: FLAGS. Values: { FLAGS, TRAITS, NAMED }." +) + +set(BEMAN_ANY_VIEW_OPTION + "COPYABLE" + CACHE + STRING + "Enable opt-in option for any_view. Default: COPYABLE. Values: { COPYABLE, MOVE_ONLY }." +) + +set(BEMAN_ANY_VIEW_USE_FLAGS OFF) +set(BEMAN_ANY_VIEW_USE_TRAITS OFF) +set(BEMAN_ANY_VIEW_USE_NAMED OFF) +set(BEMAN_ANY_VIEW_USE_COPYABLE OFF) +set(BEMAN_ANY_VIEW_USE_MOVE_ONLY OFF) + +if(BEMAN_ANY_VIEW_DESIGN STREQUAL "FLAGS") + set(BEMAN_ANY_VIEW_USE_FLAGS ON) +elseif(BEMAN_ANY_VIEW_DESIGN STREQUAL "TRAITS") + set(BEMAN_ANY_VIEW_USE_TRAITS ON) +elseif(BEMAN_ANY_VIEW_DESIGN STREQUAL "NAMED") + set(BEMAN_ANY_VIEW_USE_NAMED ON) +else() + message( + FATAL_ERROR + "BEMAN_ANY_VIEW_DESIGN must be one of { FLAGS, TRAITS, NAMED }; got ${BEMAN_ANY_VIEW_DESIGN}" + ) +endif() + +if(BEMAN_ANY_VIEW_OPTION STREQUAL "COPYABLE") + set(BEMAN_ANY_VIEW_USE_COPYABLE ON) +elseif(BEMAN_ANY_VIEW_OPTION STREQUAL "MOVE_ONLY") + set(BEMAN_ANY_VIEW_USE_MOVE_ONLY ON) +else() + message( + FATAL_ERROR + "BEMAN_ANY_VIEW_OPTION must be one of { COPYABLE, MOVE_ONLY }; got ${BEMAN_ANY_VIEW_OPTION}" + ) +endif() + +string(TOLOWER "${BEMAN_ANY_VIEW_OPTION}" BEMAN_ANY_VIEW_OPTION) + +configure_file("${PROJECT_SOURCE_DIR}/include/beman/any_view/config.hpp.in" + "${PROJECT_BINARY_DIR}/include/beman/any_view/config.hpp" @ONLY) + +include(FetchContent) +include(GNUInstallDirs) + +add_library(beman.any_view INTERFACE) +add_library(beman::any_view ALIAS beman.any_view) +target_include_directories( + beman.any_view + INTERFACE $ + $ + $) + +install( + TARGETS beman.any_view + EXPORT ${TARGETS_EXPORT_NAME} + DESTINATION $<$:debug/>${CMAKE_INSTALL_LIBDIR}) + +install( + DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${CMAKE_PROJECT_NAME} + FILES_MATCHING + PATTERN "${CMAKE_CURRENT_SOURCE_DIR}/include/beman/any_view/*.hpp") + +macro(beman_add_executable) + set(options) + set(oneValueArgs CATEGORY TARGET) + set(multiValueArgs SOURCES LIBRARIES) + + cmake_parse_arguments(beman_executable "${options}" "${oneValueArgs}" + "${multiValueArgs}" ${ARGN}) + + set(target + "beman.any_view.${beman_executable_CATEGORY}.${beman_executable_TARGET}") + + if(NOT beman_executable_SOURCES) + set(beman_executable_SOURCES "${beman_executable_TARGET}.cpp") + endif() + + add_executable(${target}) + target_sources(${target} PRIVATE ${beman_executable_SOURCES}) + target_link_libraries(${target} PRIVATE beman::any_view + ${beman_executable_LIBRARIES}) +endmacro() + +if(BEMAN_ANY_VIEW_BUILD_TESTS) + enable_testing() + + # Fetch GoogleTest + FetchContent_Declare( + googletest + GIT_REPOSITORY https://github.com/google/googletest.git + GIT_TAG v1.14.0 + EXCLUDE_FROM_ALL) + set(INSTALL_GTEST OFF) # Disable GoogleTest installation + FetchContent_MakeAvailable(googletest) + + add_subdirectory(tests/beman/any_view) +endif() diff --git a/CMakePresets.json b/CMakePresets.json new file mode 100644 index 0000000..1232dc0 --- /dev/null +++ b/CMakePresets.json @@ -0,0 +1,343 @@ +{ + "version": 6, + "configurePresets": [ + { + "name": "_root-config", + "hidden": true, + "generator": "Ninja", + "binaryDir": "${sourceDir}/build/${presetName}", + "cacheVariables": { + "CMAKE_CXX_STANDARD": "23", + "CMAKE_EXPORT_COMPILE_COMMANDS": true + } + }, + { + "name": "_debug-base", + "hidden": true, + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug", + "BEMAN_BUILDSYS_SANITIZER": "MaxSan" + } + }, + { + "name": "_release-base", + "hidden": true, + "cacheVariables": { + "CMAKE_BUILD_TYPE": "RelWithDebInfo" + } + }, + { + "name": "gcc-debug", + "displayName": "GCC Debug Build", + "inherits": [ + "_root-config", + "_debug-base" + ], + "cacheVariables": { + "CMAKE_TOOLCHAIN_FILE": "cmake/gnu-toolchain.cmake" + } + }, + { + "name": "gcc-release", + "displayName": "GCC Release Build", + "inherits": [ + "_root-config", + "_release-base" + ], + "cacheVariables": { + "CMAKE_TOOLCHAIN_FILE": "cmake/gnu-toolchain.cmake" + } + }, + { + "name": "clang-debug", + "displayName": "Clang Debug Build", + "inherits": [ + "_root-config", + "_debug-base" + ], + "cacheVariables": { + "CMAKE_TOOLCHAIN_FILE": "cmake/llvm-toolchain.cmake" + } + }, + { + "name": "clang-release", + "displayName": "Clang Release Build", + "inherits": [ + "_root-config", + "_release-base" + ], + "cacheVariables": { + "CMAKE_TOOLCHAIN_FILE": "cmake/llvm-toolchain.cmake" + } + }, + { + "name": "appleclang-debug", + "displayName": "xcode Debug Build", + "inherits": [ + "_root-config", + "_debug-base" + ], + "cacheVariables": { + "CMAKE_TOOLCHAIN_FILE": "cmake/appleclang-toolchain.cmake" + } + }, + { + "name": "appleclang-release", + "displayName": "xcode Release Build", + "inherits": [ + "_root-config", + "_release-base" + ], + "cacheVariables": { + "CMAKE_TOOLCHAIN_FILE": "cmake/appleclang-toolchain.cmake" + } + }, + { + "name": "msvc-debug", + "displayName": "MSVC Debug Build", + "inherits": [ + "_root-config", + "_debug-base" + ], + "cacheVariables": { + "CMAKE_TOOLCHAIN_FILE": "cmake/msvc-toolchain.cmake" + } + }, + { + "name": "msvc-release", + "displayName": "MSVC Release Build", + "inherits": [ + "_root-config", + "_release-base" + ], + "cacheVariables": { + "CMAKE_TOOLCHAIN_FILE": "cmake/msvc-toolchain.cmake" + } + } + ], + "buildPresets": [ + { + "name": "gcc-debug", + "configurePreset": "gcc-debug" + }, + { + "name": "gcc-release", + "configurePreset": "gcc-release" + }, + { + "name": "clang-debug", + "configurePreset": "clang-debug" + }, + { + "name": "clang-release", + "configurePreset": "clang-release" + }, + { + "name": "appleclang-debug", + "configurePreset": "appleclang-debug" + }, + { + "name": "appleclang-release", + "configurePreset": "appleclang-release" + }, + { + "name": "msvc-debug", + "configurePreset": "msvc-debug" + }, + { + "name": "msvc-release", + "configurePreset": "msvc-release" + } + ], + "testPresets": [ + { + "name": "_test_base", + "hidden": true, + "output": { + "outputOnFailure": true + }, + "execution": { + "noTestsAction": "error", + "stopOnFailure": true + } + }, + { + "name": "gcc-debug", + "inherits": "_test_base", + "configurePreset": "gcc-debug" + }, + { + "name": "gcc-release", + "inherits": "_test_base", + "configurePreset": "gcc-release" + }, + { + "name": "clang-debug", + "inherits": "_test_base", + "configurePreset": "clang-debug" + }, + { + "name": "clang-release", + "inherits": "_test_base", + "configurePreset": "clang-release" + }, + { + "name": "appleclang-debug", + "inherits": "_test_base", + "configurePreset": "appleclang-debug" + }, + { + "name": "appleclang-release", + "inherits": "_test_base", + "configurePreset": "appleclang-release" + }, + { + "name": "msvc-debug", + "inherits": "_test_base", + "configurePreset": "msvc-debug" + }, + { + "name": "msvc-release", + "inherits": "_test_base", + "configurePreset": "msvc-release" + } + ], + "workflowPresets": [ + { + "name": "gcc-debug", + "steps": [ + { + "type": "configure", + "name": "gcc-debug" + }, + { + "type": "build", + "name": "gcc-debug" + }, + { + "type": "test", + "name": "gcc-debug" + } + ] + }, + { + "name": "gcc-release", + "steps": [ + { + "type": "configure", + "name": "gcc-release" + }, + { + "type": "build", + "name": "gcc-release" + }, + { + "type": "test", + "name": "gcc-release" + } + ] + }, + { + "name": "clang-debug", + "steps": [ + { + "type": "configure", + "name": "clang-debug" + }, + { + "type": "build", + "name": "clang-debug" + }, + { + "type": "test", + "name": "clang-debug" + } + ] + }, + { + "name": "clang-release", + "steps": [ + { + "type": "configure", + "name": "clang-release" + }, + { + "type": "build", + "name": "clang-release" + }, + { + "type": "test", + "name": "clang-release" + } + ] + }, + { + "name": "appleclang-debug", + "steps": [ + { + "type": "configure", + "name": "appleclang-debug" + }, + { + "type": "build", + "name": "appleclang-debug" + }, + { + "type": "test", + "name": "appleclang-debug" + } + ] + }, + { + "name": "appleclang-release", + "steps": [ + { + "type": "configure", + "name": "appleclang-release" + }, + { + "type": "build", + "name": "appleclang-release" + }, + { + "type": "test", + "name": "appleclang-release" + } + ] + }, + { + "name": "msvc-debug", + "steps": [ + { + "type": "configure", + "name": "msvc-debug" + }, + { + "type": "build", + "name": "msvc-debug" + }, + { + "type": "test", + "name": "msvc-debug" + } + ] + }, + { + "name": "msvc-release", + "steps": [ + { + "type": "configure", + "name": "msvc-release" + }, + { + "type": "build", + "name": "msvc-release" + }, + { + "type": "test", + "name": "msvc-release" + } + ] + } + ] +} diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..0873f35 --- /dev/null +++ b/LICENSE @@ -0,0 +1,234 @@ +============================================================================== +The Beman Project is under the Apache License v2.0 with LLVM Exceptions: +============================================================================== + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +---- LLVM Exceptions to the Apache 2.0 License ---- + +As an exception, if, as a result of your compiling your source code, portions +of this Software are embedded into an Object form of such source code, you +may redistribute such embedded portions in such Object form without complying +with the conditions of Sections 4(a), 4(b) and 4(d) of the License. + +In addition, if you combine or link compiled forms of this Software with +software that is licensed under the GPLv2 ("Combined Software") and if a +court of competent jurisdiction determines that the patent provision (Section +3), the indemnity provision (Section 9) or other Section of the License +conflicts with the conditions of the GPLv2, you may retroactively and +prospectively choose to deem waived or otherwise exclude such Section(s) of +the License, but only in their entirety and only with respect to the Combined +Software. + +============================================================================== +Software from third parties included in the Beman Project: +============================================================================== +The Beman Project contains third party software which is under different license +terms. All such code will be identified clearly using at least one of two +mechanisms: +1) It will be in a separate directory tree with its own `LICENSE.txt` or + `LICENSE` file at the top containing the specific license and restrictions + which apply to that software, or +2) It will contain specific license and restriction terms at the top of every + file. diff --git a/README.md b/README.md new file mode 100644 index 0000000..58dc228 --- /dev/null +++ b/README.md @@ -0,0 +1,47 @@ + + +# beman.any_view: A generalized type-erased view with customizable properties + +![Library Status](https://github.com/bemanproject/beman/blob/c6997986557ec6dda98acbdf502082cdf7335526/images/badges/beman_badge-beman_library_under_development.svg) +![Continuous Integration Tests](https://github.com/bemanproject/any_view/actions/workflows/ci_tests.yml/badge.svg) +![Lint Check (pre-commit)](https://github.com/bemanproject/any_view/actions/workflows/pre-commit.yml/badge.svg) + +**Implements**: `std::ranges::any_view` proposed in [any_view (P3411R1)](https://wg21.link/P3411R1). + +**Status**: [Under development and not yet ready for production use.](https://github.com/bemanproject/beman/blob/main/docs/BEMAN_LIBRARY_MATURITY_MODEL.md#under-development-and-not-yet-ready-for-production-use) + +## Usage + +`std::ranges::any_view` is a class template that provides a type-erased interface for `std::ranges::view`. It may additionally model other concepts like `std::ranges::contiguous_range`, `std::ranges::sized_range`, `std::ranges::borrowed_range`, and `std::copyable` depending on the instantiation. + +## Integrate beman.any_view into your project + +
+Use beman.any_view directly from CMake + +For CMake based projects, you can include it as a dependency using the `FetchContent` module: + +```cmake +include(FetchContent) + +FetchContent_Declare( + beman.any_view + GIT_REPOSITORY https://github.com/bemanproject/any_view.git + GIT_TAG main + EXCLUDE_FROM_ALL) +FetchContent_MakeAvailable(beman.any_view) +``` + +You will also need to add `beman::any_view` to the link libraries of any targets that include `beman/any_view/*.hpp` in their source or header files: + +```cmake +target_link_libraries(yourlib PUBLIC beman::any_view) +``` + +
+ +## Contributing + +Please do! Issues and pull requests are appreciated. diff --git a/cmake/appleclang-toolchain.cmake b/cmake/appleclang-toolchain.cmake new file mode 100644 index 0000000..bc12103 --- /dev/null +++ b/cmake/appleclang-toolchain.cmake @@ -0,0 +1,39 @@ +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +# This toolchain file is not meant to be used directly, +# but to be invoked by CMake preset and GitHub CI. +# +# This toolchain file configures for apple clang family of compiler. +# Note this is different from LLVM toolchain. +# +# BEMAN_BUILDSYS_SANITIZER: +# This optional CMake parameter is not meant for public use and is subject to +# change. +# Possible values: +# - MaxSan: configures clang and clang++ to use all available non-conflicting +# sanitizers. Note that apple clang does not support leak sanitizer. +# - TSan: configures clang and clang++ to enable the use of thread sanitizer. + +include_guard(GLOBAL) + +set(CMAKE_C_COMPILER clang) +set(CMAKE_CXX_COMPILER clang++) + +if(BEMAN_BUILDSYS_SANITIZER STREQUAL "MaxSan") + set(SANITIZER_FLAGS + "-fsanitize=address -fsanitize=pointer-compare -fsanitize=pointer-subtract -fsanitize=undefined" + ) +elseif(BEMAN_BUILDSYS_SANITIZER STREQUAL "TSan") + set(SANITIZER_FLAGS "-fsanitize=thread") +endif() + +set(CMAKE_C_FLAGS_DEBUG_INIT "${SANITIZER_FLAGS}") +set(CMAKE_CXX_FLAGS_DEBUG_INIT "${SANITIZER_FLAGS}") + +set(RELEASE_FLAGS "-O3 ${SANITIZER_FLAGS}") + +set(CMAKE_C_FLAGS_RELWITHDEBINFO_INIT "${RELEASE_FLAGS}") +set(CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT "${RELEASE_FLAGS}") + +set(CMAKE_C_FLAGS_RELEASE_INIT "${RELEASE_FLAGS}") +set(CMAKE_CXX_FLAGS_RELEASE_INIT "${RELEASE_FLAGS}") diff --git a/cmake/gnu-toolchain.cmake b/cmake/gnu-toolchain.cmake new file mode 100644 index 0000000..2e2a2ad --- /dev/null +++ b/cmake/gnu-toolchain.cmake @@ -0,0 +1,38 @@ +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +# This toolchain file is not meant to be used directly, +# but to be invoked by CMake preset and GitHub CI. +# +# This toolchain file configures for GNU family of compiler. +# +# BEMAN_BUILDSYS_SANITIZER: +# This optional CMake parameter is not meant for public use and is subject to +# change. +# Possible values: +# - MaxSan: configures gcc and g++ to use all available non-conflicting +# sanitizers. +# - TSan: configures gcc and g++ to enable the use of thread sanitizer + +include_guard(GLOBAL) + +set(CMAKE_C_COMPILER gcc) +set(CMAKE_CXX_COMPILER g++) + +if(BEMAN_BUILDSYS_SANITIZER STREQUAL "MaxSan") + set(SANITIZER_FLAGS + "-fsanitize=address -fsanitize=leak -fsanitize=pointer-compare -fsanitize=pointer-subtract -fsanitize=undefined" + ) +elseif(BEMAN_BUILDSYS_SANITIZER STREQUAL "TSan") + set(SANITIZER_FLAGS "-fsanitize=thread") +endif() + +set(CMAKE_C_FLAGS_DEBUG_INIT "${SANITIZER_FLAGS}") +set(CMAKE_CXX_FLAGS_DEBUG_INIT "${SANITIZER_FLAGS}") + +set(RELEASE_FLAGS "-O3 ${SANITIZER_FLAGS}") + +set(CMAKE_C_FLAGS_RELWITHDEBINFO_INIT "${RELEASE_FLAGS}") +set(CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT "${RELEASE_FLAGS}") + +set(CMAKE_C_FLAGS_RELEASE_INIT "${RELEASE_FLAGS}") +set(CMAKE_CXX_FLAGS_RELEASE_INIT "${RELEASE_FLAGS}") diff --git a/cmake/llvm-toolchain.cmake b/cmake/llvm-toolchain.cmake new file mode 100644 index 0000000..d783803 --- /dev/null +++ b/cmake/llvm-toolchain.cmake @@ -0,0 +1,38 @@ +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +# This toolchain file is not meant to be used directly, +# but to be invoked by CMake preset and GitHub CI. +# +# This toolchain file configures for LLVM family of compiler. +# +# BEMAN_BUILDSYS_SANITIZER: +# This optional CMake parameter is not meant for public use and is subject to +# change. +# Possible values: +# - MaxSan: configures clang and clang++ to use all available non-conflicting +# sanitizers. +# - TSan: configures clang and clang++ to enable the use of thread sanitizer. + +include_guard(GLOBAL) + +set(CMAKE_C_COMPILER clang) +set(CMAKE_CXX_COMPILER clang++) + +if(BEMAN_BUILDSYS_SANITIZER STREQUAL "MaxSan") + set(SANITIZER_FLAGS + "-fsanitize=address -fsanitize=leak -fsanitize=pointer-compare -fsanitize=pointer-subtract -fsanitize=undefined" + ) +elseif(BEMAN_BUILDSYS_SANITIZER STREQUAL "TSan") + set(SANITIZER_FLAGS "-fsanitize=thread") +endif() + +set(CMAKE_C_FLAGS_DEBUG_INIT "${SANITIZER_FLAGS}") +set(CMAKE_CXX_FLAGS_DEBUG_INIT "${SANITIZER_FLAGS}") + +set(RELEASE_FLAGS "-O3 ${SANITIZER_FLAGS}") + +set(CMAKE_C_FLAGS_RELWITHDEBINFO_INIT "${RELEASE_FLAGS}") +set(CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT "${RELEASE_FLAGS}") + +set(CMAKE_C_FLAGS_RELEASE_INIT "${RELEASE_FLAGS}") +set(CMAKE_CXX_FLAGS_RELEASE_INIT "${RELEASE_FLAGS}") diff --git a/cmake/msvc-toolchain.cmake b/cmake/msvc-toolchain.cmake new file mode 100644 index 0000000..c2fffa7 --- /dev/null +++ b/cmake/msvc-toolchain.cmake @@ -0,0 +1,38 @@ +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +# This toolchain file is not meant to be used directly, +# but to be invoked by CMake preset and GitHub CI. +# +# This toolchain file configures for MSVC family of compiler. +# +# BEMAN_BUILDSYS_SANITIZER: +# This optional CMake parameter is not meant for public use and is subject to +# change. +# Possible values: +# - MaxSan: configures cl to use all available non-conflicting sanitizers. +# +# Note that in other toolchain files, TSan is also a possible value for +# BEMAN_BUILDSYS_SANITIZER, however, MSVC does not support thread sanitizer, +# thus this value is omitted. + +include_guard(GLOBAL) + +set(CMAKE_C_COMPILER cl) +set(CMAKE_CXX_COMPILER cl) + +if(BEMAN_BUILDSYS_SANITIZER STREQUAL "MaxSan") + # /Zi flag (add debug symbol) is needed when using address sanitizer + # See C5072: https://learn.microsoft.com/en-us/cpp/error-messages/compiler-warnings/compiler-warning-c5072 + set(SANITIZER_FLAGS "/fsanitize=address /Zi") +endif() + +set(CMAKE_CXX_FLAGS_DEBUG_INIT "/EHsc /permissive- ${SANITIZER_FLAGS}") +set(CMAKE_C_FLAGS_DEBUG_INIT "/EHsc /permissive- ${SANITIZER_FLAGS}") + +set(RELEASE_FLAGS "/EHsc /permissive- /O2 ${SANITIZER_FLAGS}") + +set(CMAKE_C_FLAGS_RELWITHDEBINFO_INIT "${RELEASE_FLAGS}") +set(CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT "${RELEASE_FLAGS}") + +set(CMAKE_C_FLAGS_RELEASE_INIT "${RELEASE_FLAGS}") +set(CMAKE_CXX_FLAGS_RELEASE_INIT "${RELEASE_FLAGS}") diff --git a/include/beman/any_view/any_view.hpp b/include/beman/any_view/any_view.hpp new file mode 100644 index 0000000..3421261 --- /dev/null +++ b/include/beman/any_view/any_view.hpp @@ -0,0 +1,99 @@ +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef BEMAN_ANY_VIEW_ANY_VIEW_HPP +#define BEMAN_ANY_VIEW_ANY_VIEW_HPP + +#include +#include + +#if BEMAN_ANY_VIEW_USE_FLAGS() + +#include +#include + +#elif BEMAN_ANY_VIEW_USE_TRAITS() + +#include +#include + +#elif BEMAN_ANY_VIEW_USE_NAMED() + +#include + +#endif + +namespace beman::any_view { + +#if BEMAN_ANY_VIEW_USE_FLAGS() + +template , + class DiffT = std::ptrdiff_t> +class any_view : public std::ranges::view_interface> { + using iterator_concept = detail::iterator_concept_t; + using iterator = detail::iterator; + using sentinel = std::default_sentinel_t; + + static constexpr bool sized = (OptionsV & any_view_options::sized) == any_view_options::sized; + static constexpr bool borrowed = (OptionsV & any_view_options::borrowed) == any_view_options::borrowed; + static constexpr bool BEMAN_ANY_VIEW_OPTION() = + (OptionsV & any_view_options::BEMAN_ANY_VIEW_OPTION()) == any_view_options::BEMAN_ANY_VIEW_OPTION(); + static constexpr bool simple = (OptionsV & any_view_options::simple) == any_view_options::simple; + + public: + auto begin() -> iterator; + auto end() -> sentinel; +}; + +#elif BEMAN_ANY_VIEW_USE_TRAITS() + +template +class any_view : public std::ranges::view_interface> { + using iterator_concept = detail::iterator_concept_or_t; + using reference_type = detail::reference_type_or_t; + using rvalue_reference_type = + detail::rvalue_reference_type_or_t, RangeTraitsT>; + using difference_type = detail::difference_type_or_t; + using iterator = + detail::iterator; + using sentinel = std::default_sentinel_t; + + static constexpr bool sized = detail::sized_or_v; + static constexpr bool borrowed = detail::borrowed_or_v; + static constexpr bool BEMAN_ANY_VIEW_OPTION() = detail::BEMAN_ANY_VIEW_OPTION_(or_v); + static constexpr bool simple = detail::simple_or_v; + + public: + auto begin() -> iterator; + auto end() -> sentinel; +}; + +#elif BEMAN_ANY_VIEW_USE_NAMED() + +template }> +class any_view : public std::ranges::view_interface> { + using iterator_concept = decltype(OptionsV.iterator_concept)::type; + using reference_type = decltype(OptionsV.reference_type)::type; + using rvalue_reference_type = decltype(OptionsV.rvalue_reference_type)::type; + using difference_type = decltype(OptionsV.difference_type)::type; + using iterator = + detail::iterator; + using sentinel = std::default_sentinel_t; + + static constexpr bool sized = OptionsV.sized; + static constexpr bool borrowed = OptionsV.borrowed; + static constexpr bool BEMAN_ANY_VIEW_OPTION() = OptionsV.BEMAN_ANY_VIEW_OPTION(); + static constexpr bool simple = OptionsV.simple; + + public: + auto begin() -> iterator; + auto end() -> sentinel; +}; + +#endif + +} // namespace beman::any_view + +#endif // BEMAN_ANY_VIEW_ANY_VIEW_HPP diff --git a/include/beman/any_view/any_view_options.hpp b/include/beman/any_view/any_view_options.hpp new file mode 100644 index 0000000..7287eb0 --- /dev/null +++ b/include/beman/any_view/any_view_options.hpp @@ -0,0 +1,113 @@ +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef BEMAN_ANY_VIEW_ANY_VIEW_OPTIONS_HPP +#define BEMAN_ANY_VIEW_ANY_VIEW_OPTIONS_HPP + +#include + +#if BEMAN_ANY_VIEW_USE_FLAGS() + +#include + +#elif BEMAN_ANY_VIEW_USE_NAMED() + +#include + +#include + +#endif + +namespace beman::any_view { + +#if BEMAN_ANY_VIEW_USE_FLAGS() + +enum class any_view_options { + input = 0b000000001, + forward = 0b000000011, + bidirectional = 0b000000111, + random_access = 0b000001111, + contiguous = 0b000011111, + sized = 0b000100000, + borrowed = 0b001000000, + BEMAN_ANY_VIEW_OPTION() = 0b010000000, + simple = 0b100000000, +}; + +constexpr auto operator|(any_view_options l, any_view_options r) noexcept -> any_view_options { + return any_view_options(static_cast(l) | static_cast(r)); +} + +constexpr auto operator&(any_view_options l, any_view_options r) noexcept -> any_view_options { + return any_view_options(static_cast(l) & static_cast(r)); +} + +constexpr auto operator^(any_view_options l, any_view_options r) noexcept -> any_view_options { + return any_view_options(static_cast(l) ^ static_cast(r)); +} + +constexpr auto operator~(any_view_options k) noexcept -> any_view_options { + return any_view_options(~static_cast(k)); +} + +constexpr auto operator|=(any_view_options& l, any_view_options r) noexcept -> any_view_options& { return l = l | r; } + +constexpr auto operator&=(any_view_options& l, any_view_options r) noexcept -> any_view_options& { return l = l & r; } + +constexpr auto operator^=(any_view_options& l, any_view_options r) noexcept -> any_view_options& { return l = l ^ r; } + +namespace detail { + +template +consteval auto get_iterator_concept() { + using enum any_view_options; + constexpr auto iterator_concept = OptionsV & contiguous; + + if constexpr (iterator_concept == contiguous) { + return std::contiguous_iterator_tag{}; + } else if constexpr (iterator_concept == random_access) { + return std::random_access_iterator_tag{}; + } else if constexpr (iterator_concept == bidirectional) { + return std::bidirectional_iterator_tag{}; + } else if constexpr (iterator_concept == forward) { + return std::forward_iterator_tag{}; + } else { + static_assert(iterator_concept == input); + return std::input_iterator_tag{}; + } +} + +template +using iterator_concept_t = decltype(detail::get_iterator_concept()); + +} // namespace detail + +#elif BEMAN_ANY_VIEW_USE_NAMED() + +template +struct type_t { + using type = T; +}; + +template +inline constexpr type_t type{}; + +template , + class DiffT = std::ptrdiff_t> +struct any_view_options { + type_t reference_type; + type_t iterator_concept; + bool sized; + bool BEMAN_ANY_VIEW_OPTION(); + bool borrowed; + bool simple; + type_t rvalue_reference_type; + type_t difference_type; +}; + +#endif + +} // namespace beman::any_view + +#endif // BEMAN_ANY_VIEW_ANY_VIEW_OPTIONS_HPP diff --git a/include/beman/any_view/config.hpp.in b/include/beman/any_view/config.hpp.in new file mode 100644 index 0000000..f5298a8 --- /dev/null +++ b/include/beman/any_view/config.hpp.in @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef BEMAN_ANY_VIEW_CONFIG_HPP +#define BEMAN_ANY_VIEW_CONFIG_HPP + +#cmakedefine01 BEMAN_ANY_VIEW_USE_FLAGS() +#cmakedefine01 BEMAN_ANY_VIEW_USE_TRAITS() +#cmakedefine01 BEMAN_ANY_VIEW_USE_NAMED() + +#cmakedefine01 BEMAN_ANY_VIEW_USE_COPYABLE() +#cmakedefine01 BEMAN_ANY_VIEW_USE_MOVE_ONLY() + +// clang-format off +#define BEMAN_ANY_VIEW_OPTION() @BEMAN_ANY_VIEW_OPTION@ +#define BEMAN_ANY_VIEW_OPTION_(suffix) @BEMAN_ANY_VIEW_OPTION@_##suffix +// clang-format on + +#define BEMAN_ANY_VIEW_CAT(a, b) a##b + +#endif // BEMAN_ANY_VIEW_CONFIG_HPP diff --git a/include/beman/any_view/detail/concepts.hpp b/include/beman/any_view/detail/concepts.hpp new file mode 100644 index 0000000..c2aa2f1 --- /dev/null +++ b/include/beman/any_view/detail/concepts.hpp @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef BEMAN_ANY_VIEW_DETAIL_CONCEPTS_HPP +#define BEMAN_ANY_VIEW_DETAIL_CONCEPTS_HPP + +#include + +#include + +namespace beman::any_view::detail { + +template +concept simple_range = std::ranges::range and std::ranges::range and + std::same_as, std::ranges::iterator_t> and + std::same_as, std::ranges::sentinel_t>; + +template +concept BEMAN_ANY_VIEW_OPTION_(range) = +#if BEMAN_ANY_VIEW_USE_MOVE_ONLY() + not +#endif + std::copyable and + std::ranges::range; + +} // namespace beman::any_view::detail + +#endif // BEMAN_ANY_VIEW_DETAIL_CONCEPTS_HPP diff --git a/include/beman/any_view/detail/iterator.hpp b/include/beman/any_view/detail/iterator.hpp new file mode 100644 index 0000000..0b0fc35 --- /dev/null +++ b/include/beman/any_view/detail/iterator.hpp @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef BEMAN_ANY_VIEW_DETAIL_ITERATOR_HPP +#define BEMAN_ANY_VIEW_DETAIL_ITERATOR_HPP + +#include +#include +#include + +namespace beman::any_view::detail { + +template +class iterator { + using reference = RefT; + using pointer = std::add_pointer_t; + + public: + using iterator_concept = IterConceptT; + using element_type = ElementT; + using difference_type = DiffT; + + auto operator*() const -> reference; + + auto operator->() const -> pointer; + + auto operator++() -> iterator&; + + auto operator++(int) -> iterator; + + auto operator==(const iterator&) const -> bool; + + auto operator--() -> iterator&; + + auto operator--(int) -> iterator; + + auto operator<=>(const iterator&) const -> std::partial_ordering; + + auto operator-(const iterator&) const -> difference_type; + + auto operator+=(difference_type) -> iterator&; + + auto operator+(difference_type) const -> iterator; + + friend auto operator+(difference_type, const iterator&) -> iterator; + + auto operator-=(difference_type) -> iterator&; + + auto operator-(difference_type) const -> iterator; + + auto operator[](difference_type) const -> reference; + + auto operator==(std::default_sentinel_t) const -> bool; +}; + +} // namespace beman::any_view::detail + +#endif // BEMAN_ANY_VIEW_DETAIL_ITERATOR_HPP diff --git a/include/beman/any_view/detail/type_traits.hpp b/include/beman/any_view/detail/type_traits.hpp new file mode 100644 index 0000000..e307255 --- /dev/null +++ b/include/beman/any_view/detail/type_traits.hpp @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef BEMAN_ANY_VIEW_DETAIL_TYPE_TRAITS_HPP +#define BEMAN_ANY_VIEW_DETAIL_TYPE_TRAITS_HPP + +#include + +namespace beman::any_view::detail { + +template +struct as_rvalue : std::type_identity {}; + +template +struct as_rvalue : std::type_identity {}; + +template +using as_rvalue_t = as_rvalue::type; + +} // namespace beman::any_view::detail + +#endif // BEMAN_ANY_VIEW_DETAIL_TYPE_TRAITS_HPP diff --git a/include/beman/any_view/range_traits.hpp b/include/beman/any_view/range_traits.hpp new file mode 100644 index 0000000..4b4109a --- /dev/null +++ b/include/beman/any_view/range_traits.hpp @@ -0,0 +1,101 @@ +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef BEMAN_ANY_VIEW_RANGE_TRAITS_HPP +#define BEMAN_ANY_VIEW_RANGE_TRAITS_HPP + +#include + +#if BEMAN_ANY_VIEW_USE_TRAITS() + +#include + +#include + +#endif + +namespace beman::any_view { + +#if BEMAN_ANY_VIEW_USE_TRAITS() + +namespace detail { + +template +consteval auto get_range_concept() { + if constexpr (std::ranges::contiguous_range) { + return std::contiguous_iterator_tag{}; + } else if constexpr (std::ranges::random_access_range) { + return std::random_access_iterator_tag{}; + } else if constexpr (std::ranges::bidirectional_range) { + return std::bidirectional_iterator_tag{}; + } else if constexpr (std::ranges::forward_range) { + return std::forward_iterator_tag{}; + } else { + static_assert(std::ranges::input_range); + return std::input_iterator_tag{}; + } +} + +template +using range_concept_t = decltype(detail::get_range_concept()); + +template class OpT, class... ArgsT> +struct detected_or : std::type_identity {}; + +template class OpT, class... ArgsT> + requires requires { typename OpT; } +struct detected_or : std::type_identity> {}; + +template class OpT, class... ArgsT> +using detected_or_t = detected_or::type; + +#define BEMAN_ANY_VIEW_TYPE_TRAIT(name) \ + template \ + using name##_t = RangeTraitsT::name; \ + \ + template \ + using name##_or_t = detected_or_t + +BEMAN_ANY_VIEW_TYPE_TRAIT(iterator_concept); +BEMAN_ANY_VIEW_TYPE_TRAIT(reference_type); +BEMAN_ANY_VIEW_TYPE_TRAIT(rvalue_reference_type); +BEMAN_ANY_VIEW_TYPE_TRAIT(difference_type); + +#undef BEMAN_ANY_VIEW_TYPE_TRAIT + +#define BEMAN_ANY_VIEW_BOOL_TRAIT(name) \ + template \ + using name = std::bool_constant; \ + \ + template \ + inline constexpr bool BEMAN_ANY_VIEW_CAT(name, _or_v) = \ + detected_or_t, name, RangeTraitsT>::value + +BEMAN_ANY_VIEW_BOOL_TRAIT(sized); +BEMAN_ANY_VIEW_BOOL_TRAIT(borrowed); +BEMAN_ANY_VIEW_BOOL_TRAIT(BEMAN_ANY_VIEW_OPTION()); +BEMAN_ANY_VIEW_BOOL_TRAIT(simple); + +#undef BEMAN_ANY_VIEW_BOOL_TRAIT + +} // namespace detail + +struct default_range_traits {}; + +template +struct range_traits { + using iterator_concept = detail::range_concept_t; + using reference_type = std::ranges::range_reference_t; + using rvalue_reference_type = std::ranges::range_rvalue_reference_t; + using difference_type = std::ranges::range_difference_t; + + static constexpr bool sized = std::ranges::sized_range; + static constexpr bool borrowed = std::ranges::enable_borrowed_range; + static constexpr bool BEMAN_ANY_VIEW_OPTION() = detail::BEMAN_ANY_VIEW_OPTION_(range); + static constexpr bool simple = detail::simple_range; +}; + +#endif // BEMAN_ANY_VIEW_USE_TRAITS() + +} // namespace beman::any_view + +#endif // BEMAN_ANY_VIEW_RANGE_TRAITS_HPP diff --git a/tests/beman/any_view/CMakeLists.txt b/tests/beman/any_view/CMakeLists.txt new file mode 100644 index 0000000..efa3586 --- /dev/null +++ b/tests/beman/any_view/CMakeLists.txt @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +include(GoogleTest) + +function(beman_add_test) + beman_add_executable(${ARGN} CATEGORY tests LIBRARIES GTest::gtest + GTest::gtest_main) + gtest_discover_tests(${target}) +endfunction() + +beman_add_test(TARGET concepts SOURCES concepts.test.cpp) diff --git a/tests/beman/any_view/concepts.test.cpp b/tests/beman/any_view/concepts.test.cpp new file mode 100644 index 0000000..543c951 --- /dev/null +++ b/tests/beman/any_view/concepts.test.cpp @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include + +#include + +#if BEMAN_ANY_VIEW_USE_TRAITS() + +template +struct options { + using iterator_concept = IterConceptT; +}; + +#elif BEMAN_ANY_VIEW_USE_NAMED() + +template +using options = beman::any_view::any_view_options options{ + .reference_type = beman::any_view::type, + .iterator_concept = beman::any_view::type, +}; + +#endif + +TEST(ConceptsTest, iterator_concept) { + using beman::any_view::any_view; + +#if BEMAN_ANY_VIEW_USE_FLAGS() + using options = beman::any_view::any_view_options; + + static_assert(std::ranges::input_range>); + static_assert(not std::ranges::forward_range>); + static_assert(std::ranges::forward_range>); + static_assert(not std::ranges::bidirectional_range>); + static_assert(std::ranges::bidirectional_range>); + static_assert(not std::ranges::random_access_range>); + static_assert(std::ranges::random_access_range>); + static_assert(not std::ranges::contiguous_range>); + static_assert(std::ranges::contiguous_range>); +#else + static_assert(std::ranges::input_range>>); + static_assert(not std::ranges::forward_range>>); + static_assert(std::ranges::forward_range>>); + static_assert(not std::ranges::bidirectional_range>>); + static_assert(std::ranges::bidirectional_range>>); + static_assert(not std::ranges::random_access_range>>); + static_assert(std::ranges::random_access_range>>); + static_assert(not std::ranges::contiguous_range>>); + static_assert(std::ranges::contiguous_range>>); +#endif +}