Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
9c02414
Update for Proxy
urbytes21 Jul 27, 2026
aa33130
Update for Adapter
urbytes21 Jul 27, 2026
6a79e16
Update for bridge
urbytes21 Jul 27, 2026
2b93fac
Create an demo for dlopen
urbytes21 Jul 27, 2026
91d2804
Update for decorator
urbytes21 Aug 7, 2026
60a267a
Preserve pre-existing working tree changes (tests disabled, gitignore)
urbytes21 Sep 11, 2026
13b615e
Add CLAUDE.md
urbytes21 Sep 11, 2026
00aabbf
Rewrite the lab around a self-registering example framework
urbytes21 Sep 12, 2026
5e336ee
Update documentation, scripts and CI for the new structure
urbytes21 Sep 12, 2026
d4ee7e2
Fix coverage builds and report empty --run-all filters
urbytes21 Sep 12, 2026
1b03533
Make the sources clang-tidy clean and add a Release CI job
urbytes21 Sep 12, 2026
9f043a2
Document the .clang-tidy folded-scalar trap in CLAUDE.md
urbytes21 Sep 12, 2026
a5c566d
Follow the project naming rules in the linkage and noexcept examples
urbytes21 Sep 12, 2026
ab82fe6
Explain the scratch file in tests/dummy
urbytes21 Sep 12, 2026
0bed552
Add a suggested learning path through the examples
urbytes21 Sep 12, 2026
e463c9b
Fix the clang-tidy findings and format the whole tree
urbytes21 Sep 12, 2026
87d356f
Generate the API documentation with Doxygen
urbytes21 Sep 12, 2026
f024c23
Scaffold the missing C++11-C++23 topics as draft examples
urbytes21 Sep 12, 2026
af7f049
Point the learning path and the README at the open drafts
urbytes21 Sep 12, 2026
5dedfa8
Drop an unused Doxygen PREDEFINED entry
urbytes21 Sep 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .clang-format
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,6 @@ SpacesInCStyleCastParentheses: false
SpacesInContainerLiterals: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: c++11
Standard: c++20
TabWidth: 4
UseTab: Never
40 changes: 37 additions & 3 deletions .clang-tidy
Original file line number Diff line number Diff line change
@@ -1,5 +1,26 @@
---
# Configure clang-tidy for this project.
#
# cpp-lab is a teaching repository. Examples deliberately show the "before"
# version of a pattern, copy objects so a constructor call becomes visible, read
# moved-from objects to show what happens, and spell types out instead of using
# auto. The following checks fight exactly that and are therefore disabled at
# the end of the Checks list, although they stay valuable in production code
# (note: the Checks list is a YAML folded scalar, so it cannot hold comments):
#
# -misc-use-anonymous-namespace LAB_EXAMPLE declares a static function
# -readability-convert-member-functions-to-static
# -performance-unnecessary-copy-initialization copies are made on purpose
# -performance-unnecessary-value-param pass-by-value is demonstrated
# -bugprone-use-after-move moved-from objects are inspected
# -google-runtime-int short/long are the subject of Fundamental
# -modernize-use-std-numbers the linkage constants are illustrations
# -modernize-use-auto, -modernize-loop-convert explicit code is easier to follow here
# -modernize-avoid-bind std::bind has its own example
# -modernize-use-constraints enable_if is shown next to concepts
# -misc-no-recursion recursion is the lesson (Composite, ...)
# -google-build-using-namespace chrono literals inside one function
# -google-explicit-constructor implicit conversion has its own example

# Here is an explanation for why some of the checks are disabled:
#
Expand Down Expand Up @@ -77,7 +98,6 @@
# X update.
Checks: >
-*,
abseil-*,
bugprone-*,
google-*,
misc-*,
Expand Down Expand Up @@ -115,12 +135,26 @@ Checks: >
-bugprone-implicit-widening-of-multiplication-result,
-bugprone-unchecked-optional-access,
-bugprone-unused-local-non-trivial-variable,
-bugprone-unused-return-value
-bugprone-unused-return-value,
-misc-use-anonymous-namespace,
-readability-convert-member-functions-to-static,
-performance-unnecessary-copy-initialization,
-performance-unnecessary-value-param,
-bugprone-use-after-move,
-google-runtime-int,
-modernize-use-std-numbers,
-modernize-use-auto,
-modernize-loop-convert,
-modernize-avoid-bind,
-modernize-use-constraints,
-misc-no-recursion,
-google-build-using-namespace,
-google-explicit-constructor

# Turn all the warnings from the checks above into errors.
WarningsAsErrors: "*"

HeaderFilterRegex: "(google/cloud/|generator/).*\\.h$"
HeaderFilterRegex: "(include/lab|src|tests)/.*\\.h$"

CheckOptions:
- { key: readability-identifier-naming.NamespaceCase, value: lower_case }
Expand Down
53 changes: 53 additions & 0 deletions .cppcheck-suppressions
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# cppcheck suppressions for cpp-lab

# cppcheck --suppressions-list=.cppcheck-suppressions ... ./src ./include

# Format: <id> or <id>:<file> or <id>:<file>:<line>

# --- checks that are noise in teaching code ---------------------------------
# Example classes keep their member functions non-static so the examples read
# like ordinary code.
functionStatic
# Explicit loops are often the point of an example; the algorithm version is
# shown where it is the lesson (see core/utils/Algorithm).
useStlAlgorithm

# --- intentional demonstrations ---------------------------------------------
# "the condition is always true/false" is exactly what these examples show
knownConditionTrueFalse:src/core/datatype/Fundamental.cpp
knownConditionTrueFalse:src/core/datatype/Reference.cpp
knownConditionTrueFalse:src/core/datatype/TypeConversions.cpp
knownConditionTrueFalse:src/core/string/StdString.cpp
knownConditionTrueFalse:src/core/utils/Optional.cpp
knownConditionTrueFalse:src/dp/structural/Adapter.cpp
# pointer/reference rebinding and re-assignment shown on purpose
redundantInitialization:src/core/datatype/Pointer.cpp
redundantAssignment:src/core/function/operator_overloading/AssignmentOperator.cpp
unreadVariable:src/core/datatype/TypeConversions.cpp
constVariableReference:src/core/datatype/Array.cpp
# at(3) must throw here, that is the lesson
containerOutOfBounds:src/core/container/sequence/Array.cpp
# std::deque guarantees that references survive push_front/push_back
invalidContainerReference:src/core/container/sequence/Deque.cpp
# placement new constructs into deliberately raw storage
legacyUninitvar:src/core/function/operator_overloading/AllocationOperator.cpp
# the null check after a move is the point of the example
nullPointerRedundantCheck:src/core/smart_pointer/Unique.cpp
accessMoved:src/core/class/Constructor.cpp
accessMoved:src/core/class/RuleOfThreeFiveZero.cpp
accessMoved:src/core/datatype/Reference.cpp
# classes that show what the compiler generates for them
noCopyConstructor:src/core/class/RuleOfThreeFiveZero.cpp
noOperatorEq:src/core/class/RuleOfThreeFiveZero.cpp
noCopyConstructor:src/core/class/ShallowDeepCopying.cpp
noOperatorEq:src/core/class/ShallowDeepCopying.cpp
noExplicitConstructor:src/core/class/Constructor.cpp
duplInheritedMember:src/core/class/Binding.cpp
virtualCallInConstructor:src/core/class/Binding.cpp
postfixOperator:src/core/function/operator_overloading/InDecOperator.cpp
# writing raw doubles is what binary file I/O looks like
invalidPointerCast:src/core/filehandle/BinaryFileHandling.cpp
# the plugin entry point must have main's signature
constParameter:src/demo/dlopen/sample_app.cpp
# startup code compares the linker-provided section symbols
comparePointers:src/embedded/startup.c
83 changes: 56 additions & 27 deletions .github/workflows/cpp-build-test-coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
# -------------------------------------------------------------
# Purpose:
# Runs cppcheck (static analysis), builds your C++ project,
# runs unit tests, and generates a coverage report.
# runs the unit tests and one smoke test per example,
# generates a coverage report, and repeats the tests with
# AddressSanitizer + UndefinedBehaviorSanitizer.
# -------------------------------------------------------------

name: C++ Tests and Coverage
Expand Down Expand Up @@ -45,7 +47,7 @@ jobs:
# -------------------------------------------------------
# Step 2: Run Cppcheck (Static Analysis)
# - Scans for common C++ issues (style, memory, logic)
# - You can adjust `--enable=` options as needed
# - -I include lets cppcheck understand the LAB_EXAMPLE macro
# - https://cppcheck.sourceforge.io/manual.pdf
# -------------------------------------------------------
- name: Run static analysis with Cppcheck
Expand All @@ -56,26 +58,23 @@ jobs:
--quiet \
--inline-suppr \
--error-exitcode=1 \
-I include \
--suppressions-list=.cppcheck-suppressions \
./src ./include

# -------------------------------------------------------
# Step 3: Configure and build the project
# -------------------------------------------------------
- name: Prepare build
- name: Build
run: |
rm -rf build
mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=Debug -DENABLE_COVERAGE=ON ..
cmake --build .
cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug -DENABLE_COVERAGE=ON
cmake --build build -j "$(nproc)"

# -------------------------------------------------------
# Step 4: Run unit tests
# Step 4: Run unit tests and example smoke tests
# -------------------------------------------------------
- name: Run tests
run: |
cd build
ctest --output-on-failure
run: ctest --test-dir build --output-on-failure -j "$(nproc)"

# -------------------------------------------------------
# Step 5: Generate code coverage report
Expand All @@ -97,20 +96,50 @@ jobs:
lcov --summary coverageFiltered.info >> $GITHUB_STEP_SUMMARY

# # -------------------------------------------------------
# # Step 7: Run Clang-Tidy (experimenting , not exit)
# # - Modern C++ static analysis
# # - Enforces best practices
# # - Add `--warnings-as-errors=*` to exit code 1
# # Step 7: Run Clang-Tidy (experimenting, not enforced)
# # - Modern C++ static analysis, configured by .clang-tidy
# # -------------------------------------------------------
# - name: Run clang-tidy
# # run: |
# # echo "Running clang-tidy..."
# # clang-tidy \
# # -checks='clang-analyzer-*,modernize-*,performance-*,readability-*' \
# # -p build \
# # $(find ./src -name '*.cpp')
# run: |
# echo "Running clang-tidy using .clang-tidy options"
# clang-tidy \
# -p build \
# -header-filter='^src/.*' $(find src -name "*.cpp")
# clang-tidy -p build -header-filter='^src/.*' $(find src -name "*.cpp")

release:
# ---------------------------------------------------------
# A Release build with warnings as errors: optimizations enable extra
# compiler diagnostics that a Debug build never reports.
# ---------------------------------------------------------
runs-on: ubuntu-24.04
container:
image: urboob21/cpp-lab:latest

steps:
- name: Checkout source
uses: actions/checkout@v4

- name: Build and test in Release
run: |
cmake -S . -B build-release -DCMAKE_BUILD_TYPE=Release \
-DCPPLAB_WARNINGS_AS_ERRORS=ON -DCPPLAB_BUILD_GUI=OFF
cmake --build build-release -j "$(nproc)"
ctest --test-dir build-release --output-on-failure -j "$(nproc)"

sanitizers:
# ---------------------------------------------------------
# Same tests with AddressSanitizer + UndefinedBehaviorSanitizer:
# memory errors, leaks and undefined behavior fail the job.
# ---------------------------------------------------------
runs-on: ubuntu-24.04
container:
image: urboob21/cpp-lab:latest

steps:
- name: Checkout source
uses: actions/checkout@v4

- name: Build with sanitizers
run: |
cmake -S . -B build-asan -DCMAKE_BUILD_TYPE=Debug -DCPPLAB_ENABLE_SANITIZERS=ON -DCPPLAB_BUILD_GUI=OFF
cmake --build build-asan -j "$(nproc)"

- name: Run tests with sanitizers
run: ctest --test-dir build-asan --output-on-failure -j "$(nproc)"
92 changes: 92 additions & 0 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# -------------------------------------------------------------
# GitHub Actions Workflow: API documentation (Doxygen)
# -------------------------------------------------------------
# Purpose:
# Generates the Doxygen site from the sources on every push and
# pull request (Doxygen warnings fail the job), and publishes it
# to GitHub Pages when master moves.
#
# One-time setup: Settings -> Pages -> Build and deployment ->
# Source: "GitHub Actions". See docs/doxygen.md.
# -------------------------------------------------------------

name: Docs

on:
push:
branches: [master]
pull_request:
branches: [master]
workflow_dispatch: # lets a maintainer run it by hand from the Actions tab

# Only one Pages deployment at a time; a newer run waits instead of racing.
concurrency:
group: pages
cancel-in-progress: false

jobs:
docs:
runs-on: ubuntu-24.04

permissions:
contents: read
pages: write # required by actions/deploy-pages
id-token: write # required by actions/deploy-pages (OIDC)

environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}

steps:
- name: Checkout source
uses: actions/checkout@v4

# doxygen generates the site, graphviz (dot) draws the class diagrams.
- name: Install Doxygen and Graphviz
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends doxygen graphviz cmake g++

# The docs only need the Doxyfile, so the GUI and the tests (which would
# download GoogleTest) stay off: configuring takes a second.
- name: Generate documentation
run: |
cmake -S . -B build-docs \
-DCPPLAB_BUILD_GUI=OFF \
-DCPPLAB_BUILD_TESTS=OFF \
-DCPPLAB_DOCS_WARNINGS_AS_ERRORS=ON
cmake --build build-docs --target docs

- name: Show Doxygen warnings
if: always()
run: |
echo "## Doxygen warnings" >> "$GITHUB_STEP_SUMMARY"
if [ -s build-docs/docs/doxygen-warnings.log ]; then
sed 's|^| |' build-docs/docs/doxygen-warnings.log >> "$GITHUB_STEP_SUMMARY"
else
echo "None." >> "$GITHUB_STEP_SUMMARY"
fi

# Always available as a downloadable artifact, also for pull requests.
- name: Upload the site as a build artifact
uses: actions/upload-artifact@v4
with:
name: doxygen-html
path: build-docs/docs/html
retention-days: 14

# --- Publish to GitHub Pages (pushes to master only) ---
- name: Configure GitHub Pages
if: github.event_name != 'pull_request'
uses: actions/configure-pages@v5

- name: Upload the Pages artifact
if: github.event_name != 'pull_request'
uses: actions/upload-pages-artifact@v3
with:
path: build-docs/docs/html

- name: Deploy to GitHub Pages
id: deployment
if: github.event_name != 'pull_request'
uses: actions/deploy-pages@v4
26 changes: 18 additions & 8 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
*build
*private*
.vscode/
# Build directories (build/, build-asan/, build-release/, src/embedded/build/, ...)
build/
build-*/

# Coverage reports (scripts/gen_coverage_*.sh)
coverage_gcovr/
coverage_lcov/

# CTest output when ctest runs from the repository root
Testing/

# Local-only files
/private/
.cache/
__pycache__/
*Identifier
*Testing*
coverage_gcovr
coverage_lcov

# Editor settings: keep the shared VS Code launch and task configurations
.vscode/*
!.vscode/launch.json
!.vscode/tasks.json
.cache
__pycache__/
Loading
Loading