diff --git a/.github/workflows/ci_tests.yml b/.github/workflows/ci_tests.yml
index 21454e5..06dffec 100644
--- a/.github/workflows/ci_tests.yml
+++ b/.github/workflows/ci_tests.yml
@@ -4,253 +4,129 @@ name: Continuous Integration Tests
on:
push:
+ branches:
+ - main
pull_request:
workflow_dispatch:
schedule:
- cron: '30 15 * * *'
jobs:
- beman-submodule-test:
- runs-on: ubuntu-latest
- name: "Check beman submodules for consistency"
- steps:
- - name: Checkout
- uses: actions/checkout@v4
- - name: beman submodule consistency check
- run: |
- (set -o pipefail; ./infra/tools/beman-submodule/beman-submodule status | grep -qvF '+')
+ beman-submodule-check:
+ uses: bemanproject/infra-workflows/.github/workflows/reusable-beman-submodule-check.yml@1.1.0
preset-test:
- strategy:
- fail-fast: false
- matrix:
- presets:
- - preset: "gcc-debug"
- platform: "ubuntu-latest"
- - preset: "gcc-release"
- platform: "ubuntu-latest"
- - preset: "llvm-debug"
- platform: "ubuntu-latest"
- - preset: "llvm-release"
- platform: "ubuntu-latest"
- - preset: "appleclang-debug"
- platform: "macos-latest"
- - preset: "appleclang-release"
- platform: "macos-latest"
- - preset: "msvc-debug"
- platform: "windows-latest"
- - preset: "msvc-release"
- platform: "windows-latest"
- name: "Preset: ${{ matrix.presets.preset }} on ${{ matrix.presets.platform }}"
- runs-on: ${{ matrix.presets.platform }}
- steps:
- - uses: actions/checkout@v4
- - name: Setup build environment
- uses: lukka/get-cmake@latest
- with:
- cmakeVersion: "~3.25.0"
- ninjaVersion: "^1.11.1"
- - name: Setup MSVC
- if: startsWith(matrix.presets.platform, 'windows')
- uses: TheMrMilchmann/setup-msvc-dev@v3
- with:
- arch: x64
- - name: Run preset
- run: cmake --workflow --preset ${{ matrix.presets.preset }}
-
- gtest-test:
- strategy:
- fail-fast: false
- matrix:
- platform:
- - description: "Ubuntu GNU"
- os: ubuntu-latest
- toolchain: "infra/cmake/gnu-toolchain.cmake"
- - description: "Ubuntu LLVM"
- os: ubuntu-latest
- toolchain: "infra/cmake/llvm-toolchain.cmake"
- - description: "Windows MSVC"
- os: windows-latest
- toolchain: "infra/cmake/msvc-toolchain.cmake"
- - description: "Macos Appleclang"
- os: macos-latest
- toolchain: "infra/cmake/appleclang-toolchain.cmake"
- cpp_version: [17, 20, 23, 26]
- cmake_args:
- - description: "Default"
- - description: "TSan"
- args: "-DBEMAN_BUILDSYS_SANITIZER=TSan"
- - description: "MaxSan"
- args: "-DBEMAN_BUILDSYS_SANITIZER=MaxSan"
- include:
- - platform:
- description: "Ubuntu GCC"
- os: ubuntu-latest
- toolchain: "infra/cmake/gnu-toolchain.cmake"
- cpp_version: 17
- cmake_args:
- description: "Werror"
- args: "-DCMAKE_CXX_FLAGS='-Werror=all -Werror=extra'"
- - platform:
- description: "Ubuntu GCC"
- os: ubuntu-latest
- toolchain: "infra/cmake/gnu-toolchain.cmake"
- cpp_version: 17
- cmake_args:
- description: "Dynamic"
- args: "-DBUILD_SHARED_LIBS=on"
- exclude:
- # MSVC does not support thread sanitizer
- - platform:
- description: "Windows MSVC"
- cmake_args:
- description: "TSan"
-
- name: "Unit:
- ${{ matrix.platform.description }}
- ${{ matrix.cpp_version }}
- ${{ 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: Build and Test
- uses: ./.github/actions/cmake-build-test
- with:
- cpp_version: ${{ matrix.cpp_version }}
- toolchain_file: ${{ matrix.platform.toolchain }}
- cmake_extra_args: ${{ matrix.cmake_args.args }}
-
- configuration-test:
- runs-on: ubuntu-latest
- strategy:
- fail-fast: false
- matrix:
- args:
- - name: "Disable build testing"
- arg: "-DBEMAN_CSTRING_VIEW_BUILD_TESTS=OFF"
- - name: "Disable example building"
- arg: "-DBEMAN_CSTRING_VIEW_BUILD_EXAMPLES=OFF"
- - name: "Disable config-file package creation"
- arg: "-DBEMAN_CSTRING_VIEW_INSTALL_CONFIG_FILE_PACKAGE=OFF"
- name: "CMake: ${{ matrix.args.name }}"
- steps:
- - uses: actions/checkout@v4
- - name: Setup build environment
- uses: lukka/get-cmake@latest
- with:
- cmakeVersion: "~3.25.0"
- ninjaVersion: "^1.11.1"
- - name: Build and Test
- uses: ./.github/actions/cmake-build-test
- with:
- cpp_version: 17
- toolchain_file: "infra/cmake/gnu-toolchain.cmake"
- cmake_extra_args: ${{ matrix.args.arg }}
- disable_test: true
-
- compiler-test:
- runs-on: ubuntu-24.04
- strategy:
- fail-fast: false
- matrix:
- compilers:
- - class: GNU
- version: 14
- toolchain: "infra/cmake/gnu-toolchain.cmake"
- - class: GNU
- version: 13
- toolchain: "infra/cmake/gnu-toolchain.cmake"
- - class: GNU
- version: 12
- toolchain: "infra/cmake/gnu-toolchain.cmake"
- - class: LLVM
- version: 20
- toolchain: "infra/cmake/llvm-toolchain.cmake"
- - class: LLVM
- version: 19
- toolchain: "infra/cmake/llvm-toolchain.cmake"
- - class: LLVM
- version: 18
- toolchain: "infra/cmake/llvm-toolchain.cmake"
- - class: LLVM
- version: 17
- toolchain: "infra/cmake/llvm-toolchain.cmake"
- 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: |
- sudo add-apt-repository universe
- sudo apt-get update
-
- if [ "${{ matrix.compilers.class }}" = "GNU" ]; then
- CC=gcc-${{ matrix.compilers.version }}
- CXX=g++-${{ matrix.compilers.version }}
-
- 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: Build and Test
- uses: ./.github/actions/cmake-build-test
- with:
- cpp_version: 20
- toolchain_file: ${{ matrix.compilers.toolchain }}
+ uses: bemanproject/infra-workflows/.github/workflows/reusable-beman-preset-test.yml@1.1.0
+ with:
+ matrix_config: >
+ [
+ {"preset": "gcc-debug", "image": "ghcr.io/bemanproject/infra-containers-gcc:latest"},
+ {"preset": "gcc-release", "image": "ghcr.io/bemanproject/infra-containers-gcc:latest"},
+ {"preset": "llvm-debug", "image": "ghcr.io/bemanproject/infra-containers-clang:latest"},
+ {"preset": "llvm-release", "image": "ghcr.io/bemanproject/infra-containers-clang:latest"},
+ {"preset": "appleclang-debug", "runner": "macos-latest"},
+ {"preset": "appleclang-release", "runner": "macos-latest"},
+ {"preset": "msvc-debug", "runner": "windows-latest"},
+ {"preset": "msvc-release", "runner": "windows-latest"}
+ ]
+
+ build-and-test:
+ uses: bemanproject/infra-workflows/.github/workflows/reusable-beman-build-and-test.yml@1.1.0
+ with:
+ matrix_config: >
+ {
+ "gcc": [
+ { "versions": ["15"],
+ "tests": [
+ { "cxxversions": ["c++26"],
+ "tests": [
+ { "stdlibs": ["libstdc++"],
+ "tests": [
+ "Debug.Default", "Release.Default", "Release.TSan",
+ "Release.MaxSan", "Debug.Werror", "Debug.Dynamic",
+ "Debug.Coverage"
+ ]
+ }
+ ]
+ },
+ { "cxxversions": ["c++23", "c++20"],
+ "tests": [{ "stdlibs": ["libstdc++"], "tests": ["Release.Default"]}]
+ }
+ ]
+ },
+ { "versions": ["14", "13"],
+ "tests": [
+ { "cxxversions": ["c++26", "c++23", "c++20"],
+ "tests": [{ "stdlibs": ["libstdc++"], "tests": ["Release.Default"]}]
+ }
+ ]
+ }
+ ],
+ "clang": [
+ { "versions": ["21"],
+ "tests": [
+ {"cxxversions": ["c++26"],
+ "tests": [
+ { "stdlibs": ["libstdc++", "libc++"],
+ "tests": [
+ "Debug.Default", "Release.Default", "Release.TSan",
+ "Release.MaxSan", "Debug.Werror", "Debug.Dynamic"
+ ]
+ }
+ ]
+ },
+ { "cxxversions": ["c++23", "c++20"],
+ "tests": [
+ {"stdlibs": ["libstdc++", "libc++"], "tests": ["Release.Default"]}
+ ]
+ }
+ ]
+ },
+ { "versions": ["20", "19", "18"],
+ "tests": [
+ { "cxxversions": ["c++26", "c++23", "c++20"],
+ "tests": [
+ {"stdlibs": ["libstdc++", "libc++"], "tests": ["Release.Default"]}
+ ]
+ }
+ ]
+ },
+ { "versions": ["17"],
+ "tests": [
+ { "cxxversions": ["c++26", "c++23", "c++20"],
+ "tests": [{"stdlibs": ["libc++"], "tests": ["Release.Default"]}]
+ },
+ { "cxxversions": ["c++20"],
+ "tests": [{"stdlibs": ["libstdc++"], "tests": ["Release.Default"]}]
+ }
+ ]
+ }
+ ],
+ "appleclang": [
+ { "versions": ["latest"],
+ "tests": [
+ { "cxxversions": ["c++26", "c++23", "c++20"],
+ "tests": [{ "stdlibs": ["libc++"], "tests": ["Release.Default"]}]
+ }
+ ]
+ }
+ ],
+ "msvc": [
+ { "versions": ["latest"],
+ "tests": [
+ { "cxxversions": ["c++23"],
+ "tests": [
+ { "stdlibs": ["stl"],
+ "tests": ["Debug.Default", "Release.Default", "Release.MaxSan"]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
create-issue-when-fault:
- runs-on: ubuntu-latest
- needs: [preset-test, gtest-test, configuration-test, compiler-test]
+ needs: [preset-test, build-and-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 }}
+ uses: bemanproject/infra-workflows/.github/workflows/reusable-beman-create-issue-when-fault.yml@1.1.0
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e69a90f..bbf3777 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,8 +1,10 @@
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-cmake_minimum_required(VERSION 3.25)
+cmake_minimum_required(VERSION 3.25...4.2)
-set(CMAKE_CXX_STANDARD 23)
+if(NOT DEFINED CMAKE_CXX_STANDARD)
+ set(CMAKE_CXX_STANDARD 20) # NEEDED! for std::type_identity, std::format, std::char8_t, ...!
+endif()
project(
beman.cstring_view # CMake Project Name, which is also the name of the top-level
diff --git a/CMakePresets.json b/CMakePresets.json
index 483e1a3..4a7b0ae 100644
--- a/CMakePresets.json
+++ b/CMakePresets.json
@@ -7,7 +7,6 @@
"generator": "Ninja",
"binaryDir": "${sourceDir}/build/${presetName}",
"cacheVariables": {
- "CMAKE_CXX_STANDARD": "20",
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON",
"CMAKE_PROJECT_TOP_LEVEL_INCLUDES": "./infra/cmake/use-fetch-content.cmake"
}
diff --git a/README.md b/README.md
index 319728b..dbd9987 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-->
-  
+   [
`beman.cstring_view` is a header-only `cstring_view` library.
@@ -13,6 +13,10 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
**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)
+## License
+
+`beman.exemplar` is licensed under the Apache License v2.0 with LLVM Exceptions.
+
## Usage
`std::cstring_view` exposes a string\_view like type that is intended for being able to propagate prior knowledge that
@@ -39,8 +43,8 @@ Full runnable examples can be found in [`examples/`](examples/).
This project requires at least the following to build:
-* C++17
-* CMake 3.25
+* A C++ compiler that conforms to the C++17 standard or greater
+* CMake 3.25 or later
* (Test Only) GoogleTest
You can disable building tests by setting cmake option
@@ -51,10 +55,10 @@ when configuring the project.
This project officially supports:
-* GNU GCC Compiler \[version 12-14\]
-* LLVM Clang++ Compiler \[version 17-20\]
-* AppleClang compiler on Mac OS
-* MSVC compiler on Windows
+* GCC versions 11–15
+* LLVM Clang++ (with libstdc++ or libc++) versions 17–21
+* AppleClang version 17.0.0 (i.e., the [latest version on GitHub-hosted macOS runners](https://github.com/actions/runner-images/blob/main/images/macos/macos-15-arm64-Readme.md))
+* MSVC version 19.44.35215.0 (i.e., the [latest version on GitHub-hosted Windows runners](https://github.com/actions/runner-images/blob/main/images/windows/Windows2022-Readme.md))
> [!NOTE]
>
@@ -70,7 +74,7 @@ This project officially supports:
This project supports [GitHub Codespace](https://github.com/features/codespaces)
via [Development Containers](https://containers.dev/),
which allows rapid development and instant hacking in your browser.
-We recommend you using GitHub codespace to explore this project as this
+We recommend using GitHub codespace to explore this project as it
requires minimal setup.
You can create a codespace for this project by clicking this badge:
@@ -89,11 +93,11 @@ GitHub codespaces, please reference [this doc](https://docs.github.com/en/codesp
### Develop locally on your machines
- For Linux based systems
+ For Linux
Beman libraries require [recent versions of CMake](#build-environment),
-we advise you to download CMake directly from [CMake's website](https://cmake.org/download/)
-or install it via the [Kitware apt library](https://apt.kitware.com/).
+we recommend downloading CMake directly from [CMake's website](https://cmake.org/download/)
+or installing it with the [Kitware apt library](https://apt.kitware.com/).
A [supported compiler](#supported-platforms) should be available from your package manager.
Alternatively you could use an install script from official compiler vendors.
@@ -120,10 +124,10 @@ you are using.
- For MacOS based systems
+ For MacOS
Beman libraries require [recent versions of CMake](#build-environment).
-You can use [`Homebrew`](https://brew.sh/) to install the latest major version of CMake.
+Use [`Homebrew`](https://brew.sh/) to install the latest version of CMake.
```bash
brew install cmake
@@ -175,28 +179,31 @@ cmake --workflow --preset gcc-debug
Generally, there are two kinds of presets, `debug` and `release`.
The `debug` presets are designed to aid development, so it has debugging
-instrumentation enabled and as many sanitizers turned on as possible.
+instrumentation enabled and many sanitizers enabled.
> [!NOTE]
>
-> The set of sanitizer supports are different across compilers.
-> You can checkout the exact set of compiler arguments by looking at the toolchain
-> files under the [`cmake`](cmake/) directory.
+> The sanitizers that are enabled vary from compiler to compiler.
+> See the toolchain files under ([`cmake`](cmake/)) to determine the exact configuration used for each preset.
-The `release` presets are designed for use in production environments,
-thus they have the highest optimization turned on (e.g. `O3`).
+The `release` presets are designed for production use, and
+consequently have the highest optimization turned on (e.g. `O3`).
### Configure and Build Manually
-While [CMake Presets](#configure-and-build-the-project-using-cmake-presets) are
-convenient, you might want to set different configuration or compiler arguments
-than any provided preset supports.
+If the presets are not suitable for your use-case, a traditional CMake
+invocation will provide more configurability.
To configure, build and test the project with extra arguments,
you can run this set of commands.
```bash
-cmake -B build -S . -DCMAKE_CXX_STANDARD=20 # Your extra arguments here.
+cmake \
+ -B build \
+ -S . \
+ -DCMAKE_CXX_STANDARD=20 \
+ -DCMAKE_PREFIX_PATH=$PWD/infra/cmake \
+ # Your extra arguments here.
cmake --build build
ctest --test-dir build
```
diff --git a/examples/example.cpp b/examples/example.cpp
index 5811bc2..a5c71f0 100644
--- a/examples/example.cpp
+++ b/examples/example.cpp
@@ -7,6 +7,7 @@
using namespace std::literals;
using namespace beman::literals;
+#if __cpp_impl_three_way_comparison >= 201907L
std::string_view to_string(std::strong_ordering order) {
if (order == std::strong_ordering::equal) {
return "equal";
@@ -21,6 +22,7 @@ std::string_view to_string(std::strong_ordering order) {
return "internal error";
}
}
+#endif
int main() {
std::string s = "hello world";
@@ -39,7 +41,9 @@ int main() {
std::cout << ("hello"_csv != "goodbye"sv) << "\n";
std::cout << ("hello"_csv != "goodbye"_csv) << "\n";
std::cout << (z0 == z1) << "\n";
+#if __cpp_impl_three_way_comparison >= 201907L
std::cout << to_string(z0 <=> z1) << "\n";
+#endif
std::cout << z0[z0.size()] * 1 << "\n";
std::cout << z0.c_str() << "\n";
std::cout << "\"" << empty << "\"\n";
@@ -61,7 +65,9 @@ int main() {
std::cout << (L"hello"_csv != L"goodbye"sv) << "\n";
std::cout << (L"hello"_csv != L"goodbye"_csv) << "\n";
std::cout << (wz0 == wz1) << "\n";
+#if __cpp_impl_three_way_comparison >= 201907L
std::cout << to_string(wz0 <=> wz1) << "\n";
+#endif
std::cout << wz0[wz0.size()] * 1 << "\n";
std::wcout << std::format(L"{}\n", wz0.c_str());
std::wcout << std::format(L"\"{}\"\n", wempty);
diff --git a/include/beman/cstring_view/cstring_view.hpp b/include/beman/cstring_view/cstring_view.hpp
index e71da41..172014b 100644
--- a/include/beman/cstring_view/cstring_view.hpp
+++ b/include/beman/cstring_view/cstring_view.hpp
@@ -7,6 +7,7 @@
#include
#include
#include
+#include // for std::type_identity_t
#include
#include
@@ -31,9 +32,13 @@ constexpr bool operator==(basic_cstring_view
std::type_identity_t> y) noexcept;
template
+
+#if __cpp_impl_three_way_comparison >= 201907L
constexpr auto operator<=>(basic_cstring_view x,
std::type_identity_t> y) noexcept;
+#endif
+
// [cstring.view.io], inserters and extractors
template
std::basic_ostream& operator<<(std::basic_ostream& os,
@@ -110,7 +115,7 @@ class basic_cstring_view {
// [cstring.view.cons], construction and assignment
constexpr basic_cstring_view() noexcept : size_() {
- static const charT empty_string[1]{};
+ // XXX static const charT empty_string[1]{};
data_ = std::data(empty_string);
}
constexpr basic_cstring_view(const basic_cstring_view&) noexcept = default;
@@ -313,6 +318,8 @@ class basic_cstring_view {
private:
const_pointer data_; // exposition only
size_type size_; // exposition only
+
+ static constexpr charT empty_string[1]{}; // NOLINT
};
inline namespace literals {