This repository tracks the progression from "Classic C++" to Modern C++ (C++20/23), focusing on safety, performance, and expressive syntax.
- The Problem with Raw Resources: Managing file handles (
FILE*) manually is error-prone and leads to leaks if a function returns early or throws an exception. - RAII (Resource Acquisition Is Initialization): The core C++ philosophy where an object's constructor acquires a resource and its destructor releases it.
- Deterministic Cleanup: Understanding that in C++, the destructor is guaranteed to run the moment an object goes out of scope.
- Create a
SafeFileclass that encapsulates aFILE*. - Constructor: Open the file using
fopen. - Destructor: Automatically close the file using
fclose. - Member Functions: Implement a
write()method to wrapfprintforfputsand awrite_formatted()function that uses astd::unique_ptr<char[]> bufferto write a formatted string. - Goal: Demonstrate that even if the program logic is complex, the file handle is never leaked.
- Lambdas & Captures: Writing anonymous functions with
[&]and[=]for in-place logic. - Modern Algorithms: Mastering
std::find_if,std::count_if, andstd::copy_ifwithstd::back_inserter. - C++20 Ranges: Transitioning from
.begin()/.end()to passing entire containers tostd::ranges::sort. - Exception Handling: Using
try-catchwithstd::stodto sanitize "dirty" string data.
- Filter & Convert: Use
std::for_eachandstd::stodto extract numbers from messy log strings. - Data Processing: Implement "Clamping" (capping values between 0 and 100) and outlier removal using
std::erase_if. - Numeric Reduction: Compute averages using
std::accumulate(noting the importance of0.0to avoid integer truncation).
- Advanced Sorting: Sort custom
Studentstructs in both ascending and descending order. - Searching: Find the first "Top Student" (> 90.0) and extract a list of "Failed Students" (<= 50.0).
- Shared Ownership: Managing resources with
std::shared_ptrreference counting. - Weak Observation: Using
std::weak_ptrto reference objects without extending their lifetime (preventing memory leaks from circular dependencies). - The "Lock" Pattern: Safely converting
weak_ptrtoshared_ptrbefore access to ensure the object still exists. - Encapsulation: Using
privatemembers andconstgetters to protect object integrity. - Virtual Destructors: Ensuring safe cleanup in polymorphic class hierarchies.
- The Subscriber: A base class with a
virtualdestructor and aconstmessage handler. - The Publisher: A system holding a
std::vector<std::weak_ptr<Subscriber>>. - Priority Sorting: Sorting subscribers via
std::ranges::sortbased on a priority integer. - Life-Cycle Test: Verify that the Publisher automatically "skips" subscribers that have been destroyed in local scopes.
- Modern Threading: Using
std::jthread(C++20) for auto-joining background tasks. - Data Races: Identifying why concurrent writes to shared resources (like
std::cout) cause corruption. - Mutual Exclusion: Protecting "Critical Sections" using
std::mutexandstd::lock_guard. - Atomics: Thread-safe counters using
std::atomic<T>.
- Threaded Notification: Update
Publisherto notify eachSubscriberon a separate thread. - Atomic Counters: Track successful deliveries across threads with
std::atomic<int>. - Mutex Protection: Prevent console output "scrambling" during simultaneous subscriber updates.
You are building a high-performance system for a stock trading platform. The system receives a stream of "Price Updates" (Strings) that are often messy. You need to sanitize them, calculate statistics, and notify a set of specialized "Alert Bots" (Subscribers) about the new average price—all while ensuring the system doesn't crash or leak memory.
- Input: Start with a
std::vector<std::string>of raw price data (e.g.,"150.50","ERROR","200.00","9999.99"). - Process: Use Ranges and Lambdas to:
- Convert strings to
doubleusingtry-catchandstd::stod. - Clamp outliers (e.g., cap everything at
5000.0). - Remove invalid entries or "zero" values using
std::erase_if.
- Convert strings to
- Lifecycle: Store your
AlertBotobjects inmainusingstd::shared_ptr. - Observation: The
AnalyticsEngine(Publisher) must store these bots asstd::weak_ptr. - Goal: Ensure that if a bot is disconnected (destroyed), the engine doesn't keep it alive or crash when trying to reach it.
- Parallelism: When a new batch of data is processed, the
AnalyticsEnginemust notify all bots in parallel usingstd::jthread. - Feedback: Each bot should print its unique ID and the new calculated average.
- Console Integrity: Use a
static inline std::mutexin theAlertBotclass to ensure console output isn't scrambled. - Atomic Accounting: Use a
std::atomic<int>to count exactly how many bots successfully logged the update across all threads. - The Killer Feature: One of your bots must be "temporary" (created in a small
{}scope inmain). Prove that your engine handles its sudden "death" mid-run by using the.lock()pattern safely.
[Engine]: Processing 5 new price signals...
[Engine]: Sanitization complete. New Market Average: 175.25
[Bot 1] Received Update: 175.25
[Bot 2] Received Update: 175.25
[Engine]: Successfully notified 2 active bots. (1 bot was found to be expired).
- Compiler: GCC 11+, Clang 13+, or MSVC 19.29+ (C++20 Support).
- Build System: CMake 3.15+.
- Language: C++20 / C++23
This project utilizes a strict safety strategy:
- Warnings as Errors:
-Wall -Wextra -Werrorensures no code is merged with warnings. - Address Sanitizer (ASan):
-fsanitize=addressis enabled on non-MSVC platforms to detect memory corruption at runtime.
# From the root directory:
mkdir build && cd build
cmake ..
cmake --build . ./Day1_RAII/SafeFile