From ea96d84b03808fdb0d3914da26d886c8087a9c43 Mon Sep 17 00:00:00 2001 From: Krzysiek Karbowiak Date: Fri, 3 Oct 2025 20:23:17 +0200 Subject: [PATCH 01/14] Switch C++ standard to C++23 --- CMakeLists.txt | 2 +- test/exit/CMakeLists.txt | 2 +- test/unittest/CMakeLists.txt | 2 +- tutorial/CMakeLists.txt | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4c27540e..0ff552cf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,7 +7,7 @@ add_library(${PROJECT_NAME}::${PROJECT_NAME} ALIAS ${PROJECT_NAME}) target_include_directories(${PROJECT_NAME} INTERFACE include/) -target_compile_features(${PROJECT_NAME} INTERFACE cxx_std_20) +target_compile_features(${PROJECT_NAME} INTERFACE cxx_std_23) if (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) enable_testing() diff --git a/test/exit/CMakeLists.txt b/test/exit/CMakeLists.txt index e7422ec5..ac09b877 100644 --- a/test/exit/CMakeLists.txt +++ b/test/exit/CMakeLists.txt @@ -5,7 +5,7 @@ target_sources(app PRIVATE main.cpp) -target_compile_features(app PRIVATE cxx_std_20) +target_compile_features(app PRIVATE cxx_std_23) target_compile_options(app PRIVATE $<$,$>: -Wall -Wextra -Wmisleading-indentation -Wunused diff --git a/test/unittest/CMakeLists.txt b/test/unittest/CMakeLists.txt index d4fff1b1..a909b74b 100644 --- a/test/unittest/CMakeLists.txt +++ b/test/unittest/CMakeLists.txt @@ -25,7 +25,7 @@ target_link_libraries(unittest PRIVATE cpp-argparse doctest) -target_compile_features(unittest PRIVATE cxx_std_20) +target_compile_features(unittest PRIVATE cxx_std_23) target_compile_options(unittest PRIVATE $<$,$>: -Wall -Wextra -Wmisleading-indentation -Wunused diff --git a/tutorial/CMakeLists.txt b/tutorial/CMakeLists.txt index 2401ed07..559b11ca 100644 --- a/tutorial/CMakeLists.txt +++ b/tutorial/CMakeLists.txt @@ -36,7 +36,7 @@ set(targets foreach(target ${targets}) add_executable(${target}) target_sources(${target} PRIVATE ${target}.cpp) - target_compile_features(${target} PRIVATE cxx_std_20) + target_compile_features(${target} PRIVATE cxx_std_23) target_compile_options(${target} PRIVATE $<$,$>: -Wall -Wextra -Wmisleading-indentation -Wunused From 657b746bcb3472d63f7b94d4e325695a25ec1a30 Mon Sep 17 00:00:00 2001 From: Krzysiek Karbowiak Date: Fri, 3 Oct 2025 20:30:38 +0200 Subject: [PATCH 02/14] Replace raw loops with a function --- include/argparse.hpp | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/include/argparse.hpp b/include/argparse.hpp index 43445f82..e2c2c26a 100644 --- a/include/argparse.hpp +++ b/include/argparse.hpp @@ -394,19 +394,8 @@ namespace argparse static auto join(std::ranges::view auto strings, std::string_view separator) -> std::string { - auto result = std::string(); - - for (auto const & string : strings | std::views::take(1)) - { - result += string; - } - for (auto const & string : strings | std::views::drop(1)) - { - result += separator; - result += string; - } - - return result; + auto const joined = std::ranges::fold_left_first(strings, [=](auto l, auto const & r) { l += separator; l += r; return std::move(l); }); + return joined.value_or(std::string()); } static auto parse_optional_arguments(std::ranges::view auto arguments, Tokens & tokens) -> void From 1b7bfa9c0fbaf1205368e95ed4346d8ac7f1b626 Mon Sep 17 00:00:00 2001 From: Krzysiek Karbowiak Date: Fri, 3 Oct 2025 21:00:22 +0200 Subject: [PATCH 03/14] Replace find with contains --- include/argparse.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/argparse.hpp b/include/argparse.hpp index e2c2c26a..e25b7cf2 100644 --- a/include/argparse.hpp +++ b/include/argparse.hpp @@ -1342,7 +1342,7 @@ namespace argparse { if (name[1] != '-') { - if (it->m_token.starts_with("-") && !it->m_token.starts_with("--") && it->m_token.find(name[1]) != std::string::npos) + if (it->m_token.starts_with("-") && !it->m_token.starts_with("--") && it->m_token.contains(name[1])) { return name; } From 15cdf532ccafa42381ed27761f8f253785b99e8f Mon Sep 17 00:00:00 2001 From: Krzysiek Karbowiak Date: Sat, 4 Oct 2025 09:28:45 +0200 Subject: [PATCH 04/14] Replace static cast with a function --- include/argparse.hpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/argparse.hpp b/include/argparse.hpp index e25b7cf2..8612ba60 100644 --- a/include/argparse.hpp +++ b/include/argparse.hpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -91,12 +92,12 @@ namespace argparse inline auto operator|(Handle lhs, Handle rhs) -> Handle { - return static_cast(static_cast(lhs) | static_cast(rhs)); + return static_cast(std::to_underlying(lhs) | std::to_underlying(rhs)); } inline auto operator&(Handle lhs, Handle rhs) -> int { - return static_cast(lhs) & static_cast(rhs); + return std::to_underlying(lhs) & std::to_underlying(rhs); } template From 0d5faf51358760e820fb8a223da49c8bf8b8ab3e Mon Sep 17 00:00:00 2001 From: Krzysiek Karbowiak Date: Sat, 4 Oct 2025 10:20:36 +0200 Subject: [PATCH 05/14] Exclude macOS 15 from CI --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3f11b28d..38d8bb1d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,7 +11,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [macos-15, ubuntu-24.04, windows-latest] + os: [ubuntu-24.04, windows-latest] type: [Debug, Release] compiler: [cl, clang++, g++] exclude: From d68b63bbb041ae003d956c07ad379e90db0c5e50 Mon Sep 17 00:00:00 2001 From: Krzysiek Karbowiak Date: Sat, 4 Oct 2025 15:45:29 +0200 Subject: [PATCH 06/14] Replace streaming to cout with println --- include/argparse.hpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/include/argparse.hpp b/include/argparse.hpp index 8612ba60..008d864c 100644 --- a/include/argparse.hpp +++ b/include/argparse.hpp @@ -14,10 +14,10 @@ #include #include #include -#include #include #include #include +#include #include #include #include @@ -257,7 +257,7 @@ namespace argparse { if (m_handle & Handle::help) { - std::cout << format_help() << std::endl; + std::println("{}", format_help()); std::exit(EXIT_SUCCESS); } @@ -267,7 +267,7 @@ namespace argparse { if (m_handle & Handle::version) { - std::cout << format_version() << std::endl; + std::println("{}", format_version()); std::exit(EXIT_SUCCESS); } @@ -277,8 +277,8 @@ namespace argparse { if (m_handle & Handle::errors) { - std::cout << e.what() << '\n'; - std::cout << format_help() << std::endl; + std::println("{}", e.what()); + std::println("{}", format_help()); std::exit(EXIT_FAILURE); } From f3fa03a1ca18302a3067b568be4d292ab60f2ebd Mon Sep 17 00:00:00 2001 From: Krzysiek Karbowiak Date: Sun, 5 Oct 2025 10:39:29 +0200 Subject: [PATCH 07/14] Use range function to create vector --- include/argparse.hpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/include/argparse.hpp b/include/argparse.hpp index 008d864c..c95673ca 100644 --- a/include/argparse.hpp +++ b/include/argparse.hpp @@ -568,9 +568,10 @@ namespace argparse auto transform(std::vector const & values) const -> std::any override { - auto const transformation = values - | std::views::transform([](auto const & value) { return std::any_cast(value); }); - return std::any(std::vector(transformation.begin(), transformation.end())); + return std::any( + values + | std::views::transform([](auto const & value) { return std::any_cast(value); }) + | std::ranges::to()); } auto append(std::any const & value, std::any & values) const -> void override From 46debe1b93492b2f5041d60e9ae91bf0b724b10f Mon Sep 17 00:00:00 2001 From: Krzysiek Karbowiak Date: Mon, 6 Oct 2025 23:01:24 +0200 Subject: [PATCH 08/14] Use z literal suffix --- include/argparse.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/argparse.hpp b/include/argparse.hpp index c95673ca..afbbe08c 100644 --- a/include/argparse.hpp +++ b/include/argparse.hpp @@ -1874,7 +1874,7 @@ namespace argparse if (argument.has_nargs_number()) { - for (auto n = 0u; n < argument.get_nargs_number(); n++) + for (auto n = 0uz; n < argument.get_nargs_number(); n++) { result += " " + formatted_arg; } From da0f259ddb27857f198ff75fe57a3e2368b158d5 Mon Sep 17 00:00:00 2001 From: Krzysiek Karbowiak Date: Mon, 6 Oct 2025 23:16:02 +0200 Subject: [PATCH 09/14] Replace raw loop with a range algorithm --- include/argparse.hpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/include/argparse.hpp b/include/argparse.hpp index afbbe08c..331daef4 100644 --- a/include/argparse.hpp +++ b/include/argparse.hpp @@ -1874,10 +1874,7 @@ namespace argparse if (argument.has_nargs_number()) { - for (auto n = 0uz; n < argument.get_nargs_number(); n++) - { - result += " " + formatted_arg; - } + result += std::ranges::fold_left(std::views::repeat(" " + formatted_arg, argument.get_nargs_number()), std::string(), std::plus()); } else { From bbc8460b4211bdc479128711489030b711e239bd Mon Sep 17 00:00:00 2001 From: Krzysiek Karbowiak Date: Tue, 11 Nov 2025 19:13:12 +0100 Subject: [PATCH 10/14] Switch to gcc-14 --- .github/workflows/ci.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 38d8bb1d..d0106b0e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,18 +13,18 @@ jobs: matrix: os: [ubuntu-24.04, windows-latest] type: [Debug, Release] - compiler: [cl, clang++, g++] + compiler: [cl, clang++, g++-14] exclude: - os: macos-15 compiler: cl - os: macos-15 - compiler: g++ + compiler: g++-14 - os: ubuntu-24.04 compiler: cl - os: windows-latest compiler: clang++ - os: windows-latest - compiler: g++ + compiler: g++-14 steps: - uses: actions/checkout@v5 @@ -82,7 +82,7 @@ jobs: - uses: actions/checkout@v5 - name: CMake configure - run: cmake -Bbuild -DCMAKE_BUILD_TYPE=${{ matrix.type }} -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DCMAKE_CXX_FLAGS=-fsanitize=address,undefined,leak -DCMAKE_EXE_LINKER_FLAGS=-fsanitize=address,undefined,leak + run: cmake -Bbuild -DCMAKE_BUILD_TYPE=${{ matrix.type }} -DCMAKE_C_COMPILER=gcc-14 -DCMAKE_CXX_COMPILER=g++-14 -DCMAKE_CXX_FLAGS=-fsanitize=address,undefined,leak -DCMAKE_EXE_LINKER_FLAGS=-fsanitize=address,undefined,leak - name: CMake build run: cmake --build build --parallel --target run-unit-test @@ -114,7 +114,7 @@ jobs: sudo apt install -y valgrind - name: CMake configure - run: cmake -Bbuild -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ + run: cmake -Bbuild -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=gcc-14 -DCMAKE_CXX_COMPILER=g++-14 - name: CMake build run: cmake --build build --parallel --target unittest @@ -136,7 +136,7 @@ jobs: sudo apt install -y lcov - name: CMake configure - run: cmake -Bbuild -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DCMAKE_CXX_FLAGS=--coverage -DCMAKE_EXE_LINKER_FLAGS=--coverage + run: cmake -Bbuild -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_COMPILER=gcc-14 -DCMAKE_CXX_COMPILER=g++-14 -DCMAKE_CXX_FLAGS=--coverage -DCMAKE_EXE_LINKER_FLAGS=--coverage - name: CMake build run: cmake --build build --parallel --target run-unit-test From 6135262f4e407c56612c9532178eafb54f2c5a88 Mon Sep 17 00:00:00 2001 From: Krzysiek Karbowiak Date: Tue, 11 Nov 2025 23:27:29 +0100 Subject: [PATCH 11/14] Switch to gcov-14 --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d0106b0e..e7873297 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -143,7 +143,7 @@ jobs: - name: Generate coverage run: | - lcov --directory build --capture --output-file coverage.info --ignore-errors mismatch + lcov --directory build --capture --gcov-tool gcov-14 --output-file coverage.info --ignore-errors mismatch lcov --list coverage.info lcov --extract coverage.info --output-file argparse.info *argparse.hpp lcov --list argparse.info From 4669c782933a01bfac887304060daf08f575d1ab Mon Sep 17 00:00:00 2001 From: Krzysiek Karbowiak Date: Tue, 11 Nov 2025 23:34:04 +0100 Subject: [PATCH 12/14] Revert "Exclude macOS 15 from CI" This reverts commit 0d5faf51358760e820fb8a223da49c8bf8b8ab3e. --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e7873297..b58eaac2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,7 +11,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [ubuntu-24.04, windows-latest] + os: [macos-15, ubuntu-24.04, windows-latest] type: [Debug, Release] compiler: [cl, clang++, g++-14] exclude: From 04bf14ac99f81e3da83a08bd13cc62aaa44292dc Mon Sep 17 00:00:00 2001 From: Krzysiek Karbowiak Date: Tue, 11 Nov 2025 23:59:20 +0100 Subject: [PATCH 13/14] Switch to gcc-14 on macOS --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b58eaac2..76303388 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,7 +18,7 @@ jobs: - os: macos-15 compiler: cl - os: macos-15 - compiler: g++-14 + compiler: clang++ - os: ubuntu-24.04 compiler: cl - os: windows-latest From 93050f8be1efac63a3a0cd4fcabe229c247b19a5 Mon Sep 17 00:00:00 2001 From: Krzysiek Karbowiak Date: Wed, 12 Nov 2025 00:08:50 +0100 Subject: [PATCH 14/14] Update readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bfc693b2..f237c237 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ This is a C++ implementation of Python's `argparse` module. The aim is to cover ## Dependencies -C++ argparse is a header-only library, so its setup is minimal. It has no external dependencies and only uses STL. Since it uses `std::ranges` and some other features, it requires C++20 compiler and standard library. +C++ argparse is a header-only library, so its setup is minimal. It has no external dependencies and only uses STL. Since it uses `std::ranges` and some other features, it requires C++23 compiler and standard library. In case of need, [v3.1.0](https://github.com/kkarbowiak/cpp-argparse/releases/tag/v3.1.0) is the latest release that still compiles in C++20 mode. C++ argparse uses CMake internally, but you don't have to. Just put the [argparse.hpp](https://github.com/kkarbowiak/cpp-argparse/releases/latest/download/argparse.hpp) header somewhere and point your build system to it.