Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ compile_commands.json
*.pdb
*.log
*.tmp
cpp_learning_lab_records.txt
24 changes: 21 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.20)

project(cpp_learning_lab VERSION 0.1.0 LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
Expand All @@ -28,13 +28,13 @@ endfunction()

function(cpp_lab_add_executable target_name)
add_executable(${target_name} ${ARGN})
target_compile_features(${target_name} PRIVATE cxx_std_20)
target_compile_features(${target_name} PRIVATE cxx_std_17)
cpp_lab_apply_warnings(${target_name})
endfunction()

function(cpp_lab_add_library target_name)
add_library(${target_name} ${ARGN})
target_compile_features(${target_name} PUBLIC cxx_std_20)
target_compile_features(${target_name} PUBLIC cxx_std_17)
cpp_lab_apply_warnings(${target_name})
endfunction()

Expand All @@ -45,16 +45,34 @@ cpp_lab_add_executable(en_01_types en/01_basics/types_and_initialization.cpp)
cpp_lab_add_executable(en_02_references en/02_functions_references/references_const_correctness.cpp)
cpp_lab_add_executable(en_03_class_invariants en/03_classes_oop/class_invariants.cpp)
cpp_lab_add_executable(en_03_polymorphism en/03_classes_oop/polymorphism_virtual_destructor.cpp)
cpp_lab_add_executable(en_03_object_slicing en/03_classes_oop/object_slicing_warning.cpp)
cpp_lab_add_executable(en_04_raii en/04_raii_memory/raii_unique_ptr.cpp)
cpp_lab_add_executable(en_05_stl en/05_stl/vector_algorithm_basics.cpp)
cpp_lab_add_executable(en_06_smart_pointers en/06_smart_pointers/unique_shared_weak.cpp)
cpp_lab_add_executable(en_07_move_semantics en/07_move_semantics/rule_of_zero_and_move.cpp)
cpp_lab_add_executable(en_08_error_handling en/08_error_handling/optional_exceptions_status.cpp)
cpp_lab_add_executable(en_09_file_io en/09_file_io/file_stream_records.cpp)
cpp_lab_add_executable(en_10_templates en/10_templates/template_repository.cpp)
cpp_lab_add_executable(en_11_low_level en/11_low_level_cpp/bytes_alignment_flags.cpp)
cpp_lab_add_executable(en_12_concurrency en/12_concurrency/thread_safe_counter.cpp)
cpp_lab_add_executable(en_13_patterns en/13_patterns_architecture/strategy_pattern.cpp)

cpp_lab_add_executable(tr_00_merhaba tr/00_toolchain/hello_modern_cpp.cpp)
cpp_lab_add_executable(tr_01_tipler tr/01_basics/types_and_initialization.cpp)
cpp_lab_add_executable(tr_02_referanslar tr/02_functions_references/references_const_correctness.cpp)
cpp_lab_add_executable(tr_03_sinif_kurallari tr/03_classes_oop/class_invariants.cpp)
cpp_lab_add_executable(tr_03_polimorfizm tr/03_classes_oop/polymorphism_virtual_destructor.cpp)
cpp_lab_add_executable(tr_03_object_slicing tr/03_classes_oop/object_slicing_warning.cpp)
cpp_lab_add_executable(tr_04_raii tr/04_raii_memory/raii_unique_ptr.cpp)
cpp_lab_add_executable(tr_05_stl tr/05_stl/vector_algorithm_basics.cpp)
cpp_lab_add_executable(tr_06_smart_pointerlar tr/06_smart_pointers/unique_shared_weak.cpp)
cpp_lab_add_executable(tr_07_move_semantics tr/07_move_semantics/rule_of_zero_and_move.cpp)
cpp_lab_add_executable(tr_08_hata_yonetimi tr/08_error_handling/optional_exceptions_status.cpp)
cpp_lab_add_executable(tr_09_file_io tr/09_file_io/file_stream_records.cpp)
cpp_lab_add_executable(tr_10_templates tr/10_templates/template_repository.cpp)
cpp_lab_add_executable(tr_11_low_level tr/11_low_level_cpp/bytes_alignment_flags.cpp)
cpp_lab_add_executable(tr_12_concurrency tr/12_concurrency/thread_safe_counter.cpp)
cpp_lab_add_executable(tr_13_patterns tr/13_patterns_architecture/strategy_pattern.cpp)

add_subdirectory(en/projects/bank_account_oop)
add_subdirectory(tr/projects/bank_account_oop)
63 changes: 44 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,35 +1,44 @@
# cpp-learning-lab

Modern C++ Systems Foundation is a long-term C++ learning and reference lab.
The goal is not to collect random snippets. The goal is to build a repository
that explains C++ topics deeply enough to be useful later in interviews,
internships, embedded or systems work, and offline review.
The goal is not to collect random snippets. The goal is to build a practical
offline reference for interviews, internships, embedded or systems work, and
daily syntax recall.

This repository is designed around three layers:

1. Language foundation: syntax, types, references, functions, classes, and OOP.
2. Engineering foundation: RAII, ownership, STL, tests, CMake, and CI.
3. Systems mindset: memory layout, performance, concurrency, low-level behavior,
1. Language foundation: types, functions, references, classes, and OOP.
2. Engineering foundation: RAII, ownership, STL, templates, tests, CMake, and CI.
3. Systems mindset: memory layout, file I/O, concurrency, low-level behavior,
and production-style project structure.

## Standard Policy

The repository uses **C++17 as the build baseline** because it is widely
available in production toolchains. C++20 and C++23 features are introduced as
modern notes where they matter, but the compiled examples stay portable and
industry-friendly.

## Repository Structure

```txt
.
├── docs/ # Build, style, debugging, and topic templates
├── en/ # English learning track
├── tr/ # Turkish learning track
├── CMakeLists.txt # Root build configuration
└── .github/workflows/ # CI build and test automation
|-- docs/ # Build, style, debugging, and topic templates
|-- en/ # English learning track
|-- tr/ # Turkish learning track
|-- CMakeLists.txt # Root build configuration
`-- .github/workflows/ # CI build and test automation
```

## Current Foundation

- C++20-based build setup with CMake.
- C++17-based build setup with CMake.
- Compiler warnings enabled for examples and projects.
- GitHub Actions build and test workflow.
- English and Turkish learning paths.
- First examples for toolchain, types, references, OOP, RAII, and STL.
- English and Turkish learning paths and reference indexes.
- Examples for toolchain, types, references, OOP, RAII, smart pointers, move
semantics, STL, templates, error handling, file I/O, low-level C++, threading,
and architecture patterns.
- A modular OOP bank account project with library, demo, and tests.

## How To Build
Expand All @@ -55,9 +64,25 @@ ctest --test-dir build --output-on-failure
- [English learning path](en/LEARNING_PATH.md)
- [Turkish learning path](tr/LEARNING_PATH.md)

## Direction
## Topic Map

- `00_toolchain`: compiler, CMake, CI, and build habits.
- `01_basics`: types, initialization, `auto`, and basic standard library usage.
- `02_functions_references`: function design, references, `const`, and intent.
- `03_classes_oop`: class invariants, encapsulation, inheritance, polymorphism.
- `04_raii_memory`: RAII, lifetime, ownership, and resource cleanup.
- `05_stl`: standard containers and algorithms.
- `06_smart_pointers`: `unique_ptr`, `shared_ptr`, `weak_ptr`, and ownership.
- `07_move_semantics`: copy, move, Rule of 0, and Rule of 5 direction.
- `08_error_handling`: exceptions, `std::optional`, and status-style returns.
- `09_file_io`: stream-based text record I/O.
- `10_templates`: reusable type-safe generic code.
- `11_low_level_cpp`: bytes, alignment, flags, and systems mental model.
- `12_concurrency`: threads, mutexes, and safe shared state.
- `13_patterns_architecture`: small design patterns without overengineering.

## Maintenance Rule

The next phases will deepen OOP, RAII, smart pointers, move semantics, STL,
templates, error handling, concurrency, and low-level C++ topics. Each serious
topic should include explanation, mistakes, real-world usage, exercises, and
working code.
Add new material only when it teaches a real C++ idea, compiles cleanly, and is
linked from the learning path. The repository should stay useful as a handbook,
not become a pile of disconnected examples.
2 changes: 1 addition & 1 deletion docs/build-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ built in one consistent way.

## Requirements

- A C++20-capable compiler:
- A C++17-capable compiler:
- GCC 10+
- Clang 12+
- MSVC 19.29+
Expand Down
32 changes: 32 additions & 0 deletions docs/cpp-standard-policy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# C++ Standard Policy

This repository uses C++17 as the compiled baseline.

## Why C++17?

- It is widely supported by GCC, Clang, and MSVC.
- It is common in production codebases that cannot upgrade toolchains quickly.
- It contains important modern features such as structured bindings,
`std::optional`, `std::variant`, `std::string_view`, and improved constexpr.
- It is a stable foundation before introducing C++20 features such as concepts,
ranges, coroutines, and modules.

## How C++20 Fits

C++20 should be explained in notes and future optional examples, especially for:

- concepts
- ranges
- `std::span`
- coroutines
- modules
- stronger compile-time programming

The default build should stay C++17 unless a topic explicitly needs a newer
standard.

## Practical Rule

Learn modern C++ style, but keep examples compatible with realistic company
toolchains. That balance is useful for interviews, embedded work, and restricted
development environments.
36 changes: 36 additions & 0 deletions docs/repo-roadmap.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Repository Roadmap

The repository is organized as a compact handbook. Each topic has a README for
the mental model and one focused example that compiles in CI.

## Stable Foundation

- Toolchain and CMake.
- Basic types and initialization.
- Functions, references, and const-correctness.
- OOP, invariants, polymorphism, and virtual destructors.
- RAII, smart pointers, and move semantics.
- STL containers and algorithms.
- Templates and generic code.
- Error handling, file I/O, low-level C++, and concurrency.

## Project Layer

The `bank_account_oop` project is intentionally small but production-shaped:

- public header in `include/`
- implementation in `src/`
- demo executable in `src/main.cpp`
- assert-based tests in `tests/`
- CMake integration

Future projects should follow this structure instead of becoming single-file
scripts.

## Done Criteria For New Topics

- The topic has a README.
- The example compiles through root CMake.
- The topic is linked from `LEARNING_PATH.md`.
- The code teaches a real concept, not only syntax.
- Naming and formatting match the rest of the repository.
3 changes: 3 additions & 0 deletions en/03_classes_oop/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,12 @@ modeling ownership, and deciding when runtime polymorphism is worth the cost.
- Prefer composition before inheritance.
- Use a virtual destructor for polymorphic base classes.
- Avoid object slicing when working with derived objects.
- Pass polymorphic objects by reference or pointer, not by value.

## Examples

- `class_invariants.cpp`: constructor validation and private state.
- `polymorphism_virtual_destructor.cpp`: abstract base class and virtual
destructor.
- `object_slicing_warning.cpp`: why passing derived objects by base value loses
derived behavior.
35 changes: 35 additions & 0 deletions en/03_classes_oop/object_slicing_warning.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#include <iostream>
#include <string>

class Notification {
public:
virtual ~Notification() = default;

virtual std::string channel() const {
return "generic";
}
};

class EmailNotification final : public Notification {
public:
std::string channel() const override {
return "email";
}
};

void printByValue(Notification notification) {
std::cout << "by value: " << notification.channel() << '\n';
}

void printByReference(const Notification& notification) {
std::cout << "by reference: " << notification.channel() << '\n';
}

int main() {
EmailNotification email;

printByValue(email);
printByReference(email);

return 0;
}
5 changes: 2 additions & 3 deletions en/03_classes_oop/polymorphism_virtual_destructor.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
#include <cmath>
#include <iostream>
#include <memory>
#include <numbers>
#include <vector>

class Shape {
Expand All @@ -17,7 +15,8 @@ class Circle final : public Shape {
explicit Circle(double radius) : radius_{radius} {}

double area() const override {
return std::numbers::pi * radius_ * radius_;
constexpr double pi = 3.14159265358979323846;
return pi * radius_ * radius_;
}

void print() const override {
Expand Down
23 changes: 23 additions & 0 deletions en/06_smart_pointers/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Smart Pointers

Smart pointers make ownership visible in the type system. They do not remove
the need to understand lifetime, but they make common lifetime mistakes harder.

## Mental Model

- `std::unique_ptr<T>` means one owner.
- `std::shared_ptr<T>` means shared ownership.
- `std::weak_ptr<T>` observes a shared object without extending its lifetime.
- Raw pointers and references are usually non-owning views in modern C++.

## Common Mistakes

- Using `shared_ptr` everywhere because it feels convenient.
- Creating ownership cycles with `shared_ptr`.
- Returning raw owning pointers from factory functions.
- Keeping a raw pointer after the owner has destroyed the object.

## Example

- `unique_shared_weak.cpp`: compares single ownership, shared ownership, and
non-owning observation.
51 changes: 51 additions & 0 deletions en/06_smart_pointers/unique_shared_weak.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#include <iostream>
#include <memory>
#include <string>
#include <utility>

class Sensor {
public:
Sensor(std::string name, int value) : name_{std::move(name)}, value_{value} {}

const std::string& name() const noexcept {
return name_;
}

int read() const noexcept {
return value_;
}

private:
std::string name_;
int value_;
};

class Dashboard {
public:
explicit Dashboard(std::weak_ptr<Sensor> sensor) : sensor_{std::move(sensor)} {}

void print() const {
if (const auto sensor = sensor_.lock()) {
std::cout << sensor->name() << ": " << sensor->read() << '\n';
} else {
std::cout << "sensor is no longer available\n";
}
}

private:
std::weak_ptr<Sensor> sensor_;
};

int main() {
auto uniqueSensor = std::make_unique<Sensor>("temperature", 24);
std::cout << uniqueSensor->name() << ": " << uniqueSensor->read() << '\n';

auto sharedSensor = std::make_shared<Sensor>("pressure", 101);
Dashboard dashboard{sharedSensor};

dashboard.print();
sharedSensor.reset();
dashboard.print();

return 0;
}
20 changes: 20 additions & 0 deletions en/07_move_semantics/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Move Semantics

Move semantics allow resources to be transferred instead of copied. They are
central to modern C++ performance and ownership design.

## Mental Model

- Copying duplicates a value.
- Moving transfers resources from one object to another.
- A moved-from object must remain valid, but its old value should not be relied
on unless the type documents it.
- Rule of 0: prefer standard library members so the compiler can generate copy,
move, and destruction behavior.
- Rule of 5: if a class manually owns a resource, think about destructor, copy
constructor, copy assignment, move constructor, and move assignment together.

## Example

- `rule_of_zero_and_move.cpp`: shows a resource-owning wrapper that can use the
Rule of 0 because `std::vector` manages memory.
Loading
Loading