From 9e64042e8dbff6edaebc18ebff15fdf78da63a14 Mon Sep 17 00:00:00 2001 From: Zhihua Lai Date: Tue, 16 Dec 2025 13:55:30 +0000 Subject: [PATCH] fold example, make format check --- Makefile | 24 ++++++++++ README.md | 14 ++++++ fold-left-fold-right/Makefile | 29 ++++++++++++ fold-left-fold-right/main.cpp | 85 +++++++++++++++++++++++++++++++++++ thread-safe-queue/Makefile | 6 ++- unique-ptr-basics/Makefile | 6 ++- views-zip-enumerate/Makefile | 6 ++- 7 files changed, 167 insertions(+), 3 deletions(-) create mode 100644 fold-left-fold-right/Makefile create mode 100644 fold-left-fold-right/main.cpp diff --git a/Makefile b/Makefile index 9ef44ba..8d30722 100644 --- a/Makefile +++ b/Makefile @@ -35,3 +35,27 @@ clean: @for dir in $(SUBDIRS); do \ $(MAKE) -C $$dir clean; \ done + +.PHONY: check-format-all check-format + +check-format-all: + @for dir in $(SUBDIRS); do \ + if [ -d "$$dir" ]; then \ + echo "=== clang-format check in $$dir ==="; \ + $(MAKE) -f $(MAKEFILE_LIST) check-format DIR=$$dir; \ + fi; \ + done + +check-format: + @cd $(DIR); \ + echo "Checking clang-format in $(DIR)"; \ + if command -v bash >/dev/null 2>&1; then \ + bash -c 'shopt -s nullglob; files=( *.cpp *.hpp *.c *.h ); \ + if [ $${#files[@]} -ne 0 ]; then \ + clang-format --Werror --dry-run "$${files[@]}"; \ + else \ + echo "No source files found, skipping"; \ + fi'; \ + else \ + echo "Bash not found; skipping clang-format check"; \ + fi diff --git a/README.md b/README.md index 9fddb60..1532cac 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,8 @@ Examples include (and will expand to): * Views * [views-zip-enumerate](./views-zip-enumerate/) * Atomics and memory ordering +* Folding + * [fold-left-fold-right](./fold-left-fold-right/) * RAII and ownership patterns * Performance‑oriented C++ idioms @@ -140,6 +142,18 @@ The `clang-format` is used to ensure the code format. ./clang-check.sh *.cpp *.hpp ``` +At top level, you can do: + +```make +make check-format-all +``` + +At each example directory, you can do: + +```make +make check-format +``` + --- ## Continuous Integration diff --git a/fold-left-fold-right/Makefile b/fold-left-fold-right/Makefile new file mode 100644 index 0000000..bd77cf7 --- /dev/null +++ b/fold-left-fold-right/Makefile @@ -0,0 +1,29 @@ +# pull in shared compiler settings +include ../common.mk + +# per-example flags +CXXFLAGS += -pthread + +TARGET := fold_left_fold_right +SRCS := main.cpp +OBJS := $(SRCS:.cpp=.o) + +all: $(TARGET) + +$(TARGET): $(OBJS) + $(CXX) $(CXXFLAGS) -o $@ $^ + +%.o: %.cpp + $(CXX) $(CXXFLAGS) -c $< -o $@ + +run: $(TARGET) + ./$(TARGET) $(ARGS) + +clean: + rm -f $(OBJS) $(TARGET) + +# Delegates to top-level Makefile +check-format: + $(MAKE) -f ../Makefile check-format DIR=$(CURDIR) + +.PHONY: all clean run check-format diff --git a/fold-left-fold-right/main.cpp b/fold-left-fold-right/main.cpp new file mode 100644 index 0000000..7b877a1 --- /dev/null +++ b/fold-left-fold-right/main.cpp @@ -0,0 +1,85 @@ +#include +#include +#include // accumulate, fold_* +#include // std::plus +#include + +template +T +fold_left(const Range& r, T init, Op op) +{ + for (auto&& v : r) + init = op(init, v); + return init; +} + +template +T +fold_right(const Range& r, T init, Op op) +{ + for (auto it = r.rbegin(); it != r.rend(); ++it) + init = op(*it, init); + return init; +} + +// fold_left_first: uses the first element of the range as the initial value +template +std::optional +fold_left_first(const Range& r, Op op) +{ + auto it = r.begin(); + if (it == r.end()) + return std::nullopt; + auto init = *it++; + for (; it != r.end(); ++it) + init = op(init, *it); + return init; +} + +// fold_right_first: uses the first element of the range as the initial value +template +std::optional +fold_right_first(const Range& r, Op op) +{ + auto it = r.rbegin(); + if (it == r.rend()) + return std::nullopt; + auto init = *it++; + for (; it != r.rend(); ++it) + init = op(*it, init); + return init; +} + +int +main() +{ + std::vector numbers = {1, 2, 3, 4, 5}; + + // Fold left (classic) + int sum_left = std::accumulate(numbers.begin(), numbers.end(), 0, std::plus{}); + std::cout << "Fold left (sum): " << sum_left << '\n'; + + // Fold right (classic using reverse iterators) + int sum_right = std::accumulate(numbers.rbegin(), numbers.rend(), 0, std::plus{}); + std::cout << "Fold right (sum): " << sum_right << '\n'; + + // Fold left with ranges (C++23) + int sum_ranges = fold_left(numbers, 0, std::plus{}); + std::cout << "Fold left with ranges (sum): " << sum_ranges << '\n'; + + // Fold right with ranges (C++23) + int sum_ranges_right = fold_right(numbers, 0, std::plus{}); + std::cout << "Fold right with ranges (sum): " << sum_ranges_right << '\n'; + + // Fold left using first element as initial value + if (auto sum_first = fold_left_first(numbers, std::plus{})) { + std::cout << "Fold left first element (sum): " << *sum_first << '\n'; + } + + // Fold right using first element as initial value + if (auto sum_right_first = fold_right_first(numbers, std::plus{})) { + std::cout << "Fold right first element (sum): " << *sum_right_first << '\n'; + } + + return 0; +} diff --git a/thread-safe-queue/Makefile b/thread-safe-queue/Makefile index ed0679c..a6aa96b 100644 --- a/thread-safe-queue/Makefile +++ b/thread-safe-queue/Makefile @@ -22,4 +22,8 @@ run: $(TARGET) clean: rm -f $(OBJS) $(TARGET) -.PHONY: all clean run +# Delegates to top-level Makefile +check-format: + $(MAKE) -f ../Makefile check-format DIR=$(CURDIR) + +.PHONY: all clean run check-format diff --git a/unique-ptr-basics/Makefile b/unique-ptr-basics/Makefile index 1b5bad8..337df4f 100644 --- a/unique-ptr-basics/Makefile +++ b/unique-ptr-basics/Makefile @@ -19,4 +19,8 @@ run: $(TARGET) clean: rm -f $(OBJS) $(TARGET) -.PHONY: all clean run +# Delegates to top-level Makefile +check-format: + $(MAKE) -f ../Makefile check-format DIR=$(CURDIR) + +.PHONY: all clean run check-format diff --git a/views-zip-enumerate/Makefile b/views-zip-enumerate/Makefile index e1b7434..a5b354c 100644 --- a/views-zip-enumerate/Makefile +++ b/views-zip-enumerate/Makefile @@ -22,4 +22,8 @@ run: $(TARGET) clean: rm -f $(OBJS) $(TARGET) -.PHONY: all clean run +# Delegates to top-level Makefile +check-format: + $(MAKE) -f ../Makefile check-format DIR=$(CURDIR) + +.PHONY: all clean run check-format