From 199b57a675922c7a85a4d95c2690f3776937c13a Mon Sep 17 00:00:00 2001 From: hp Date: Mon, 18 May 2026 16:51:45 +0300 Subject: [PATCH] Expand C++ handbook coverage --- CMakeLists.txt | 24 ++++++++ README.md | 15 ++++- docs/coverage-map.md | 31 ++++++++++ docs/repo-roadmap.md | 16 ++++++ en/14_core_language_details/README.md | 23 ++++++++ .../scope_enum_static.cpp | 53 ++++++++++++++++++ en/15_strings_views/README.md | 22 ++++++++ en/15_strings_views/string_string_view.cpp | 29 ++++++++++ en/16_containers_iterators/README.md | 23 ++++++++ .../map_set_iterator.cpp | 31 ++++++++++ en/17_lambdas_algorithms/README.md | 23 ++++++++ .../lambda_algorithm_pipeline.cpp | 40 +++++++++++++ en/18_compile_time_constexpr/README.md | 23 ++++++++ .../constexpr_lookup.cpp | 21 +++++++ en/19_variant_tuple_enum/README.md | 22 ++++++++ .../variant_tuple_enum.cpp | 35 ++++++++++++ en/20_operator_overloading/README.md | 21 +++++++ .../value_type_operator.cpp | 42 ++++++++++++++ en/21_namespaces_headers/README.md | 22 ++++++++ .../namespace_api_design.cpp | 33 +++++++++++ en/22_casts_type_safety/README.md | 23 ++++++++ en/22_casts_type_safety/casts_type_safety.cpp | 27 +++++++++ en/23_testing_practices/README.md | 23 ++++++++ .../simple_test_harness.cpp | 39 +++++++++++++ en/24_filesystem_chrono/README.md | 21 +++++++ en/24_filesystem_chrono/filesystem_chrono.cpp | 22 ++++++++ en/25_atomics_intro/README.md | 23 ++++++++ en/25_atomics_intro/atomic_counter.cpp | 29 ++++++++++ en/LEARNING_PATH.md | 56 +++++++++++++------ en/README.md | 12 ++++ en/REFERENCE_INDEX.md | 12 ++++ tr/14_core_language_details/README.md | 23 ++++++++ .../scope_enum_static.cpp | 53 ++++++++++++++++++ tr/15_strings_views/README.md | 22 ++++++++ tr/15_strings_views/string_string_view.cpp | 29 ++++++++++ tr/16_containers_iterators/README.md | 22 ++++++++ .../map_set_iterator.cpp | 31 ++++++++++ tr/17_lambdas_algorithms/README.md | 23 ++++++++ .../lambda_algorithm_pipeline.cpp | 40 +++++++++++++ tr/18_compile_time_constexpr/README.md | 23 ++++++++ .../constexpr_lookup.cpp | 21 +++++++ tr/19_variant_tuple_enum/README.md | 22 ++++++++ .../variant_tuple_enum.cpp | 35 ++++++++++++ tr/20_operator_overloading/README.md | 21 +++++++ .../value_type_operator.cpp | 42 ++++++++++++++ tr/21_namespaces_headers/README.md | 22 ++++++++ .../namespace_api_design.cpp | 33 +++++++++++ tr/22_casts_type_safety/README.md | 23 ++++++++ tr/22_casts_type_safety/casts_type_safety.cpp | 27 +++++++++ tr/23_testing_practices/README.md | 23 ++++++++ .../simple_test_harness.cpp | 39 +++++++++++++ tr/24_filesystem_chrono/README.md | 21 +++++++ tr/24_filesystem_chrono/filesystem_chrono.cpp | 22 ++++++++ tr/25_atomics_intro/README.md | 22 ++++++++ tr/25_atomics_intro/atomic_counter.cpp | 29 ++++++++++ tr/LEARNING_PATH.md | 56 +++++++++++++------ tr/README.md | 12 ++++ tr/REFERENCE_INDEX.md | 12 ++++ 58 files changed, 1551 insertions(+), 33 deletions(-) create mode 100644 docs/coverage-map.md create mode 100644 en/14_core_language_details/README.md create mode 100644 en/14_core_language_details/scope_enum_static.cpp create mode 100644 en/15_strings_views/README.md create mode 100644 en/15_strings_views/string_string_view.cpp create mode 100644 en/16_containers_iterators/README.md create mode 100644 en/16_containers_iterators/map_set_iterator.cpp create mode 100644 en/17_lambdas_algorithms/README.md create mode 100644 en/17_lambdas_algorithms/lambda_algorithm_pipeline.cpp create mode 100644 en/18_compile_time_constexpr/README.md create mode 100644 en/18_compile_time_constexpr/constexpr_lookup.cpp create mode 100644 en/19_variant_tuple_enum/README.md create mode 100644 en/19_variant_tuple_enum/variant_tuple_enum.cpp create mode 100644 en/20_operator_overloading/README.md create mode 100644 en/20_operator_overloading/value_type_operator.cpp create mode 100644 en/21_namespaces_headers/README.md create mode 100644 en/21_namespaces_headers/namespace_api_design.cpp create mode 100644 en/22_casts_type_safety/README.md create mode 100644 en/22_casts_type_safety/casts_type_safety.cpp create mode 100644 en/23_testing_practices/README.md create mode 100644 en/23_testing_practices/simple_test_harness.cpp create mode 100644 en/24_filesystem_chrono/README.md create mode 100644 en/24_filesystem_chrono/filesystem_chrono.cpp create mode 100644 en/25_atomics_intro/README.md create mode 100644 en/25_atomics_intro/atomic_counter.cpp create mode 100644 tr/14_core_language_details/README.md create mode 100644 tr/14_core_language_details/scope_enum_static.cpp create mode 100644 tr/15_strings_views/README.md create mode 100644 tr/15_strings_views/string_string_view.cpp create mode 100644 tr/16_containers_iterators/README.md create mode 100644 tr/16_containers_iterators/map_set_iterator.cpp create mode 100644 tr/17_lambdas_algorithms/README.md create mode 100644 tr/17_lambdas_algorithms/lambda_algorithm_pipeline.cpp create mode 100644 tr/18_compile_time_constexpr/README.md create mode 100644 tr/18_compile_time_constexpr/constexpr_lookup.cpp create mode 100644 tr/19_variant_tuple_enum/README.md create mode 100644 tr/19_variant_tuple_enum/variant_tuple_enum.cpp create mode 100644 tr/20_operator_overloading/README.md create mode 100644 tr/20_operator_overloading/value_type_operator.cpp create mode 100644 tr/21_namespaces_headers/README.md create mode 100644 tr/21_namespaces_headers/namespace_api_design.cpp create mode 100644 tr/22_casts_type_safety/README.md create mode 100644 tr/22_casts_type_safety/casts_type_safety.cpp create mode 100644 tr/23_testing_practices/README.md create mode 100644 tr/23_testing_practices/simple_test_harness.cpp create mode 100644 tr/24_filesystem_chrono/README.md create mode 100644 tr/24_filesystem_chrono/filesystem_chrono.cpp create mode 100644 tr/25_atomics_intro/README.md create mode 100644 tr/25_atomics_intro/atomic_counter.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 5f651ed..936973b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -56,6 +56,18 @@ 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(en_14_core_language en/14_core_language_details/scope_enum_static.cpp) +cpp_lab_add_executable(en_15_strings_views en/15_strings_views/string_string_view.cpp) +cpp_lab_add_executable(en_16_containers en/16_containers_iterators/map_set_iterator.cpp) +cpp_lab_add_executable(en_17_lambdas en/17_lambdas_algorithms/lambda_algorithm_pipeline.cpp) +cpp_lab_add_executable(en_18_constexpr en/18_compile_time_constexpr/constexpr_lookup.cpp) +cpp_lab_add_executable(en_19_variant_tuple en/19_variant_tuple_enum/variant_tuple_enum.cpp) +cpp_lab_add_executable(en_20_operator_overloading en/20_operator_overloading/value_type_operator.cpp) +cpp_lab_add_executable(en_21_namespaces en/21_namespaces_headers/namespace_api_design.cpp) +cpp_lab_add_executable(en_22_casts en/22_casts_type_safety/casts_type_safety.cpp) +cpp_lab_add_executable(en_23_testing en/23_testing_practices/simple_test_harness.cpp) +cpp_lab_add_executable(en_24_filesystem_chrono en/24_filesystem_chrono/filesystem_chrono.cpp) +cpp_lab_add_executable(en_25_atomics en/25_atomics_intro/atomic_counter.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) @@ -73,6 +85,18 @@ 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) +cpp_lab_add_executable(tr_14_core_language tr/14_core_language_details/scope_enum_static.cpp) +cpp_lab_add_executable(tr_15_strings_views tr/15_strings_views/string_string_view.cpp) +cpp_lab_add_executable(tr_16_containers tr/16_containers_iterators/map_set_iterator.cpp) +cpp_lab_add_executable(tr_17_lambdas tr/17_lambdas_algorithms/lambda_algorithm_pipeline.cpp) +cpp_lab_add_executable(tr_18_constexpr tr/18_compile_time_constexpr/constexpr_lookup.cpp) +cpp_lab_add_executable(tr_19_variant_tuple tr/19_variant_tuple_enum/variant_tuple_enum.cpp) +cpp_lab_add_executable(tr_20_operator_overloading tr/20_operator_overloading/value_type_operator.cpp) +cpp_lab_add_executable(tr_21_namespaces tr/21_namespaces_headers/namespace_api_design.cpp) +cpp_lab_add_executable(tr_22_casts tr/22_casts_type_safety/casts_type_safety.cpp) +cpp_lab_add_executable(tr_23_testing tr/23_testing_practices/simple_test_harness.cpp) +cpp_lab_add_executable(tr_24_filesystem_chrono tr/24_filesystem_chrono/filesystem_chrono.cpp) +cpp_lab_add_executable(tr_25_atomics tr/25_atomics_intro/atomic_counter.cpp) add_subdirectory(en/projects/bank_account_oop) add_subdirectory(tr/projects/bank_account_oop) diff --git a/README.md b/README.md index 4fef3c9..0ad3f17 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,8 @@ industry-friendly. - 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. + lambdas, compile-time programming, strings/views, casts, testing, filesystem, + chrono, atomics, and architecture patterns. - A modular OOP bank account project with library, demo, and tests. ## How To Build @@ -80,6 +81,18 @@ ctest --test-dir build --output-on-failure - `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. +- `14_core_language_details`: scope, `enum class`, `static`, and state control. +- `15_strings_views`: `std::string`, `std::string_view`, and text lifetime. +- `16_containers_iterators`: map, set, iterator usage, and container choice. +- `17_lambdas_algorithms`: captures, predicates, transforms, and algorithm use. +- `18_compile_time_constexpr`: `constexpr`, `static_assert`, compile-time data. +- `19_variant_tuple_enum`: `std::variant`, `std::tuple`, and alternative data. +- `20_operator_overloading`: value-type operators without surprising behavior. +- `21_namespaces_headers`: API boundaries, namespaces, and header discipline. +- `22_casts_type_safety`: explicit casts and safer downcasting. +- `23_testing_practices`: simple deterministic tests and failure behavior. +- `24_filesystem_chrono`: portable paths and type-safe time measurement. +- `25_atomics_intro`: atomic counters and shared state basics. ## Maintenance Rule diff --git a/docs/coverage-map.md b/docs/coverage-map.md new file mode 100644 index 0000000..6906a7b --- /dev/null +++ b/docs/coverage-map.md @@ -0,0 +1,31 @@ +# Coverage Map + +This repository is meant to be a practical C++ handbook, not a copy of the +entire language standard. The default coverage is complete for foundation and +intermediate review. + +## Covered For Daily Work + +- build tools, CMake, and CI +- basic types, initialization, scope, `enum class`, and `static` +- functions, references, const-correctness, and API intent +- classes, encapsulation, invariants, polymorphism, virtual destructors, object + slicing, and operator overloading +- RAII, smart pointers, ownership, move semantics, Rule of 0, and Rule of 5 +- STL containers, iterators, algorithms, lambdas, strings, and string views +- templates, `constexpr`, `std::optional`, `std::variant`, and `std::tuple` +- file I/O, filesystem, chrono, casts, low-level bytes, flags, and alignment +- threads, mutexes, atomics, testing practices, and simple architecture patterns + +## Not The Main Target + +These topics are useful but should not block the handbook from being practical: + +- advanced template metaprogramming +- custom allocators +- lock-free data structures +- coroutine frameworks +- modules in production build systems +- compiler-specific embedded register maps + +Add those only when there is a concrete learning or work need. diff --git a/docs/repo-roadmap.md b/docs/repo-roadmap.md index fded7ff..4124428 100644 --- a/docs/repo-roadmap.md +++ b/docs/repo-roadmap.md @@ -13,6 +13,8 @@ the mental model and one focused example that compiles in CI. - STL containers and algorithms. - Templates and generic code. - Error handling, file I/O, low-level C++, and concurrency. +- Lambdas, strings/views, associative containers, constexpr, variant/tuple, + casts, operator overloading, testing, filesystem/chrono, and atomics. ## Project Layer @@ -34,3 +36,17 @@ scripts. - 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. + +## Advanced Topics Kept As Notes + +Some modern C++ features are intentionally not required by the default build +because the repository targets a C++17 production baseline: + +- C++20 concepts +- C++20 ranges +- C++20 coroutines +- C++20 modules +- C++23 library additions + +These can be added later as optional notes or separate examples without making +the main handbook harder to build in conservative toolchains. diff --git a/en/14_core_language_details/README.md b/en/14_core_language_details/README.md new file mode 100644 index 0000000..0f2a181 --- /dev/null +++ b/en/14_core_language_details/README.md @@ -0,0 +1,23 @@ +# Core Language Details + +Small language rules shape large C++ programs. Scopes, `enum class`, `static`, +`const`, and namespaces help keep names and state controlled. + +## Mental Model + +- Scope decides where a name is visible. +- `enum class` avoids unscoped integer-like enum pollution. +- `static` local variables keep state between calls. +- `static` class members belong to the class, not one object. +- Prefer explicit ownership and explicit state over hidden globals. + +## Common Mistakes + +- Using unscoped `enum` values that collide with other names. +- Hiding state in globals when a class or function parameter would be clearer. +- Confusing `const` object state with compile-time constants. + +## Example + +- `scope_enum_static.cpp`: shows controlled names, scoped enum values, and class + level state. diff --git a/en/14_core_language_details/scope_enum_static.cpp b/en/14_core_language_details/scope_enum_static.cpp new file mode 100644 index 0000000..1b52dbd --- /dev/null +++ b/en/14_core_language_details/scope_enum_static.cpp @@ -0,0 +1,53 @@ +#include +#include + +enum class LogLevel { + info, + warning, + error, +}; + +std::string toString(const LogLevel level) { + switch (level) { + case LogLevel::info: + return "info"; + case LogLevel::warning: + return "warning"; + case LogLevel::error: + return "error"; + } + + return "unknown"; +} + +class Logger { +public: + explicit Logger(LogLevel minimumLevel) : minimumLevel_{minimumLevel} { + ++createdCount_; + } + + void print(LogLevel level, const std::string& message) const { + if (static_cast(level) >= static_cast(minimumLevel_)) { + std::cout << "[" << toString(level) << "] " << message << '\n'; + } + } + + static int createdCount() noexcept { + return createdCount_; + } + +private: + LogLevel minimumLevel_; + static int createdCount_; +}; + +int Logger::createdCount_ = 0; + +int main() { + Logger logger{LogLevel::warning}; + logger.print(LogLevel::info, "hidden"); + logger.print(LogLevel::error, "shown"); + + std::cout << "logger count: " << Logger::createdCount() << '\n'; + return 0; +} diff --git a/en/15_strings_views/README.md b/en/15_strings_views/README.md new file mode 100644 index 0000000..dc07818 --- /dev/null +++ b/en/15_strings_views/README.md @@ -0,0 +1,22 @@ +# Strings And Views + +`std::string` owns text. `std::string_view` observes text. Knowing the +difference prevents needless copies and dangling views. + +## Mental Model + +- `std::string` stores and owns characters. +- `std::string_view` points at existing characters and does not own them. +- Use `std::string_view` for read-only function parameters when the function + does not store the view. +- Never return a `string_view` to a local `std::string`. + +## Common Mistakes + +- Storing a `string_view` after the original string has been destroyed. +- Using C-style string functions when `std::string` is enough. +- Passing large strings by value when no copy is needed. + +## Example + +- `string_string_view.cpp`: trims and checks text without copying it. diff --git a/en/15_strings_views/string_string_view.cpp b/en/15_strings_views/string_string_view.cpp new file mode 100644 index 0000000..ae59d16 --- /dev/null +++ b/en/15_strings_views/string_string_view.cpp @@ -0,0 +1,29 @@ +#include +#include +#include + +std::string_view trimSpaces(std::string_view text) noexcept { + while (!text.empty() && text.front() == ' ') { + text.remove_prefix(1); + } + + while (!text.empty() && text.back() == ' ') { + text.remove_suffix(1); + } + + return text; +} + +bool startsWith(std::string_view text, std::string_view prefix) noexcept { + return text.size() >= prefix.size() && text.substr(0, prefix.size()) == prefix; +} + +int main() { + const std::string command{" upload:file.txt "}; + const std::string_view trimmed = trimSpaces(command); + + std::cout << "trimmed: " << trimmed << '\n'; + std::cout << "is upload: " << std::boolalpha << startsWith(trimmed, "upload:") << '\n'; + + return 0; +} diff --git a/en/16_containers_iterators/README.md b/en/16_containers_iterators/README.md new file mode 100644 index 0000000..174de6c --- /dev/null +++ b/en/16_containers_iterators/README.md @@ -0,0 +1,23 @@ +# Containers And Iterators + +STL containers solve different storage and lookup problems. Iterators are the +common access model that lets algorithms work with many containers. + +## Mental Model + +- `std::vector` is the default sequence container. +- `std::map` keeps keys ordered. +- `std::unordered_map` optimizes average lookup by hash. +- `std::set` stores unique sorted values. +- Iterators point into containers; invalidation rules matter. + +## Common Mistakes + +- Choosing `map` when unordered lookup would be enough. +- Erasing from a container while using an invalidated iterator. +- Using a container without thinking about lookup and iteration needs. + +## Example + +- `map_set_iterator.cpp`: builds a frequency table and extracts sorted unique + keys. diff --git a/en/16_containers_iterators/map_set_iterator.cpp b/en/16_containers_iterators/map_set_iterator.cpp new file mode 100644 index 0000000..d822ada --- /dev/null +++ b/en/16_containers_iterators/map_set_iterator.cpp @@ -0,0 +1,31 @@ +#include +#include +#include +#include +#include + +int main() { + const std::vector tags{ + "cpp", + "systems", + "cpp", + "oop", + "systems", + "templates", + }; + + std::map frequencies; + std::set uniqueTags; + + for (const auto& tag : tags) { + ++frequencies[tag]; + uniqueTags.insert(tag); + } + + for (auto it = frequencies.begin(); it != frequencies.end(); ++it) { + std::cout << it->first << " -> " << it->second << '\n'; + } + + std::cout << "unique tag count: " << uniqueTags.size() << '\n'; + return 0; +} diff --git a/en/17_lambdas_algorithms/README.md b/en/17_lambdas_algorithms/README.md new file mode 100644 index 0000000..680ea9e --- /dev/null +++ b/en/17_lambdas_algorithms/README.md @@ -0,0 +1,23 @@ +# Lambdas And Algorithms + +Lambdas let behavior stay close to the algorithm that uses it. They are most +useful when paired with standard algorithms. + +## Mental Model + +- `[]` is the capture list. +- `[value]` captures by value. +- `[&value]` captures by reference. +- Prefer algorithms when they express intent more clearly than manual loops. +- Keep lambdas short and named with variables when they become important. + +## Common Mistakes + +- Capturing references that outlive the referenced object. +- Writing a long lambda that should be a named function. +- Using `for_each` when a simple range-for loop is clearer. + +## Example + +- `lambda_algorithm_pipeline.cpp`: filters, transforms, and sums values with + lambdas and algorithms. diff --git a/en/17_lambdas_algorithms/lambda_algorithm_pipeline.cpp b/en/17_lambdas_algorithms/lambda_algorithm_pipeline.cpp new file mode 100644 index 0000000..c3dcc2b --- /dev/null +++ b/en/17_lambdas_algorithms/lambda_algorithm_pipeline.cpp @@ -0,0 +1,40 @@ +#include +#include +#include +#include +#include + +struct Order { + std::string customer; + double total; +}; + +int main() { + std::vector orders{ + {"Ada", 120.0}, + {"Bjarne", 80.0}, + {"Grace", 210.0}, + }; + + const double minimum = 100.0; + const auto isLargeOrder = [minimum](const Order& order) { + return order.total >= minimum; + }; + + std::vector largeTotals; + for (const auto& order : orders) { + if (isLargeOrder(order)) { + largeTotals.push_back(order.total); + } + } + + std::transform(largeTotals.begin(), largeTotals.end(), largeTotals.begin(), [](double total) { + return total * 1.20; + }); + + const double sum = std::accumulate(largeTotals.begin(), largeTotals.end(), 0.0); + + std::cout << "large order count: " << largeTotals.size() << '\n'; + std::cout << "taxed total: " << sum << '\n'; + return 0; +} diff --git a/en/18_compile_time_constexpr/README.md b/en/18_compile_time_constexpr/README.md new file mode 100644 index 0000000..ed0c947 --- /dev/null +++ b/en/18_compile_time_constexpr/README.md @@ -0,0 +1,23 @@ +# Compile-Time And Constexpr + +C++ can compute some values at compile time. This improves safety and can remove +runtime work when the inputs are known early. + +## Mental Model + +- `const` means the value cannot be modified through that name. +- `constexpr` means the value or function can participate in compile-time + evaluation. +- `static_assert` checks a condition during compilation. +- Compile-time code should still stay readable. + +## Common Mistakes + +- Assuming every `const` value is compile-time. +- Making code `constexpr` before it needs to be. +- Hiding complicated runtime logic in compile-time tricks. + +## Example + +- `constexpr_lookup.cpp`: computes small lookup values and validates them with + `static_assert`. diff --git a/en/18_compile_time_constexpr/constexpr_lookup.cpp b/en/18_compile_time_constexpr/constexpr_lookup.cpp new file mode 100644 index 0000000..2871a40 --- /dev/null +++ b/en/18_compile_time_constexpr/constexpr_lookup.cpp @@ -0,0 +1,21 @@ +#include +#include + +constexpr int square(const int value) noexcept { + return value * value; +} + +constexpr std::array makeSquares() { + return {square(0), square(1), square(2), square(3), square(4)}; +} + +int main() { + constexpr auto squares = makeSquares(); + static_assert(squares[4] == 16, "square table is wrong"); + + for (const int value : squares) { + std::cout << value << '\n'; + } + + return 0; +} diff --git a/en/19_variant_tuple_enum/README.md b/en/19_variant_tuple_enum/README.md new file mode 100644 index 0000000..5925ce9 --- /dev/null +++ b/en/19_variant_tuple_enum/README.md @@ -0,0 +1,22 @@ +# Variant, Tuple, And Enum + +Some data can be one of several known alternatives. C++17 gives `std::variant` +for type-safe alternatives and `std::tuple` for fixed groups of values. + +## Mental Model + +- `enum class` names a closed set of states. +- `std::variant` stores exactly one of the listed types. +- `std::visit` handles the active variant alternative. +- `std::tuple` groups values when a small named struct would be too much. +- Prefer a named struct when field names matter. + +## Common Mistakes + +- Using inheritance when a `variant` would model alternatives more simply. +- Using tuple fields so heavily that names would be clearer. +- Forgetting to handle every variant alternative. + +## Example + +- `variant_tuple_enum.cpp`: models messages as known alternatives. diff --git a/en/19_variant_tuple_enum/variant_tuple_enum.cpp b/en/19_variant_tuple_enum/variant_tuple_enum.cpp new file mode 100644 index 0000000..2b9cd47 --- /dev/null +++ b/en/19_variant_tuple_enum/variant_tuple_enum.cpp @@ -0,0 +1,35 @@ +#include +#include +#include +#include + +struct LoginEvent { + std::string user; +}; + +struct ErrorEvent { + int code; + std::string message; +}; + +using Event = std::variant; + +struct EventPrinter { + void operator()(const LoginEvent& event) const { + std::cout << "login: " << event.user << '\n'; + } + + void operator()(const ErrorEvent& event) const { + std::cout << "error " << event.code << ": " << event.message << '\n'; + } +}; + +int main() { + const Event event = ErrorEvent{404, "not found"}; + std::visit(EventPrinter{}, event); + + const std::tuple summary{1, "processed"}; + std::cout << std::get<0>(summary) << " -> " << std::get<1>(summary) << '\n'; + + return 0; +} diff --git a/en/20_operator_overloading/README.md b/en/20_operator_overloading/README.md new file mode 100644 index 0000000..c9ff57c --- /dev/null +++ b/en/20_operator_overloading/README.md @@ -0,0 +1,21 @@ +# Operator Overloading + +Operator overloading should make value types feel natural. It should not hide +expensive work or surprising side effects. + +## Mental Model + +- Overload operators for value types such as money, vectors, or IDs. +- Keep operators consistent with normal expectations. +- Prefer named functions when the operation is domain-specific. +- Implement compound assignment first when useful, then derive binary operators. + +## Common Mistakes + +- Overloading operators for clever syntax instead of clarity. +- Making `operator+` modify the left-hand object. +- Forgetting `const` correctness. + +## Example + +- `value_type_operator.cpp`: implements a small `Money` value type. diff --git a/en/20_operator_overloading/value_type_operator.cpp b/en/20_operator_overloading/value_type_operator.cpp new file mode 100644 index 0000000..d8ca5a3 --- /dev/null +++ b/en/20_operator_overloading/value_type_operator.cpp @@ -0,0 +1,42 @@ +#include +#include + +class Money { +public: + explicit Money(int cents) : cents_{cents} {} + + int cents() const noexcept { + return cents_; + } + + Money& operator+=(const Money other) noexcept { + cents_ += other.cents_; + return *this; + } + +private: + int cents_; +}; + +Money operator+(Money lhs, const Money rhs) noexcept { + lhs += rhs; + return lhs; +} + +bool operator==(const Money lhs, const Money rhs) noexcept { + return lhs.cents() == rhs.cents(); +} + +std::ostream& operator<<(std::ostream& output, const Money money) { + return output << money.cents() / 100 << "." << money.cents() % 100; +} + +int main() { + const Money salary{125'000}; + const Money bonus{25'000}; + const Money total = salary + bonus; + + std::cout << "total: " << total << '\n'; + std::cout << "matches expected: " << std::boolalpha << (total == Money{150'000}) << '\n'; + return 0; +} diff --git a/en/21_namespaces_headers/README.md b/en/21_namespaces_headers/README.md new file mode 100644 index 0000000..4f2db68 --- /dev/null +++ b/en/21_namespaces_headers/README.md @@ -0,0 +1,22 @@ +# Namespaces And Header Design + +Large C++ projects need boundaries. Namespaces and headers make APIs visible +without exposing every implementation detail. + +## Mental Model + +- A header declares the public interface. +- A source file defines implementation details. +- Namespaces prevent name collisions. +- Keep headers small because every include affects compile time. +- Prefer including what you use instead of relying on indirect includes. + +## Common Mistakes + +- Putting `using namespace std;` in a header. +- Exposing private helper functions in public headers. +- Including heavy headers when a forward declaration would be enough. + +## Example + +- `namespace_api_design.cpp`: simulates a small namespaced API in one file. diff --git a/en/21_namespaces_headers/namespace_api_design.cpp b/en/21_namespaces_headers/namespace_api_design.cpp new file mode 100644 index 0000000..ee81a43 --- /dev/null +++ b/en/21_namespaces_headers/namespace_api_design.cpp @@ -0,0 +1,33 @@ +#include +#include +#include + +namespace telemetry { +class Reading { +public: + Reading(std::string name, double value) : name_{std::move(name)}, value_{value} {} + + const std::string& name() const noexcept { + return name_; + } + + double value() const noexcept { + return value_; + } + +private: + std::string name_; + double value_; +}; + +std::string format(const Reading& reading) { + return reading.name() + "=" + std::to_string(reading.value()); +} +} // namespace telemetry + +int main() { + const telemetry::Reading reading{"temperature", 24.5}; + std::cout << telemetry::format(reading) << '\n'; + + return 0; +} diff --git a/en/22_casts_type_safety/README.md b/en/22_casts_type_safety/README.md new file mode 100644 index 0000000..b3eff7b --- /dev/null +++ b/en/22_casts_type_safety/README.md @@ -0,0 +1,23 @@ +# Casts And Type Safety + +C++ casts should be visible and intentional. A cast is often a sign that two +parts of the program disagree about types. + +## Mental Model + +- `static_cast` is for checked-at-compile-time conversions. +- `dynamic_cast` is for safe downcasting through polymorphic bases. +- `const_cast` changes constness and should be rare. +- `reinterpret_cast` treats bits as another type and belongs near low-level + boundaries. +- Prefer designing APIs that avoid casts. + +## Common Mistakes + +- Using C-style casts because they are shorter. +- Downcasting when virtual functions would be cleaner. +- Narrowing numbers without checking range. + +## Example + +- `casts_type_safety.cpp`: shows numeric casts and safe polymorphic downcast. diff --git a/en/22_casts_type_safety/casts_type_safety.cpp b/en/22_casts_type_safety/casts_type_safety.cpp new file mode 100644 index 0000000..b9e12dc --- /dev/null +++ b/en/22_casts_type_safety/casts_type_safety.cpp @@ -0,0 +1,27 @@ +#include +#include + +class Device { +public: + virtual ~Device() = default; +}; + +class SensorDevice final : public Device { +public: + int sample() const noexcept { + return 42; + } +}; + +int main() { + const double rawValue = 42.9; + const int roundedDown = static_cast(rawValue); + std::cout << "rounded down: " << roundedDown << '\n'; + + std::unique_ptr device = std::make_unique(); + if (const auto* sensor = dynamic_cast(device.get())) { + std::cout << "sample: " << sensor->sample() << '\n'; + } + + return 0; +} diff --git a/en/23_testing_practices/README.md b/en/23_testing_practices/README.md new file mode 100644 index 0000000..03b103b --- /dev/null +++ b/en/23_testing_practices/README.md @@ -0,0 +1,23 @@ +# Testing Practices + +Tests protect behavior while you refactor. Even a tiny test harness is better +than manually running a program and reading output every time. + +## Mental Model + +- Test observable behavior, not private implementation details. +- Keep tests deterministic. +- Test edge cases and failure paths. +- A failing test should stop the build. +- For real projects, use a test framework; for learning examples, a small + helper can be enough. + +## Common Mistakes + +- Testing only the happy path. +- Depending on test execution order. +- Printing failures but still returning success. + +## Example + +- `simple_test_harness.cpp`: a tiny framework-free test runner. diff --git a/en/23_testing_practices/simple_test_harness.cpp b/en/23_testing_practices/simple_test_harness.cpp new file mode 100644 index 0000000..61001c1 --- /dev/null +++ b/en/23_testing_practices/simple_test_harness.cpp @@ -0,0 +1,39 @@ +#include +#include +#include +#include +#include + +int clamp(const int value, const int low, const int high) { + if (low > high) { + throw std::invalid_argument{"low cannot be greater than high"}; + } + if (value < low) { + return low; + } + if (value > high) { + return high; + } + return value; +} + +void require(const bool condition, const std::string& message) { + if (!condition) { + throw std::runtime_error{message}; + } +} + +int main() { + const std::vector> tests{ + {"value inside range", []() { require(clamp(5, 1, 10) == 5, "inside range failed"); }}, + {"value below range", []() { require(clamp(-1, 1, 10) == 1, "below range failed"); }}, + {"value above range", []() { require(clamp(99, 1, 10) == 10, "above range failed"); }}, + }; + + for (const auto& test : tests) { + test.second(); + std::cout << "passed: " << test.first << '\n'; + } + + return 0; +} diff --git a/en/24_filesystem_chrono/README.md b/en/24_filesystem_chrono/README.md new file mode 100644 index 0000000..582dc2b --- /dev/null +++ b/en/24_filesystem_chrono/README.md @@ -0,0 +1,21 @@ +# Filesystem And Chrono + +C++17 added standard filesystem support. `std::chrono` gives type-safe time +durations and timestamps. + +## Mental Model + +- `std::filesystem::path` represents paths portably. +- Use filesystem functions instead of manual string path manipulation. +- `std::chrono::duration` represents an amount of time. +- `std::chrono::time_point` represents a point in time. + +## Common Mistakes + +- Building paths with raw string concatenation. +- Mixing milliseconds and seconds as plain integers. +- Assuming path separators are the same on every operating system. + +## Example + +- `filesystem_chrono.cpp`: creates a path and measures a small operation. diff --git a/en/24_filesystem_chrono/filesystem_chrono.cpp b/en/24_filesystem_chrono/filesystem_chrono.cpp new file mode 100644 index 0000000..cb5f756 --- /dev/null +++ b/en/24_filesystem_chrono/filesystem_chrono.cpp @@ -0,0 +1,22 @@ +#include +#include +#include +#include +#include + +int main() { + const std::filesystem::path base{"build"}; + const std::filesystem::path report = base / "report.txt"; + + const auto start = std::chrono::steady_clock::now(); + const std::vector values{1, 2, 3, 4, 5}; + const int sum = std::accumulate(values.begin(), values.end(), 0); + const auto end = std::chrono::steady_clock::now(); + + const auto elapsed = std::chrono::duration_cast(end - start); + + std::cout << "report path: " << report.string() << '\n'; + std::cout << "sum: " << sum << '\n'; + std::cout << "elapsed microseconds: " << elapsed.count() << '\n'; + return 0; +} diff --git a/en/25_atomics_intro/README.md b/en/25_atomics_intro/README.md new file mode 100644 index 0000000..3c554f2 --- /dev/null +++ b/en/25_atomics_intro/README.md @@ -0,0 +1,23 @@ +# Atomics Intro + +Atomics let simple shared values be updated without a mutex. They are powerful, +but they are not a replacement for understanding thread ownership and invariants. + +## Mental Model + +- `std::atomic` makes operations on `T` atomic. +- Atomic counters are simple; lock-free algorithms are advanced. +- Prefer mutexes for compound state and invariants. +- Start with default sequentially consistent ordering before learning weaker + memory orders. + +## Common Mistakes + +- Assuming atomics automatically make a whole object thread-safe. +- Mixing atomic and non-atomic access to the same value. +- Using relaxed memory ordering without a proof. + +## Example + +- `atomic_counter.cpp`: increments a shared atomic counter from multiple + threads. diff --git a/en/25_atomics_intro/atomic_counter.cpp b/en/25_atomics_intro/atomic_counter.cpp new file mode 100644 index 0000000..493e202 --- /dev/null +++ b/en/25_atomics_intro/atomic_counter.cpp @@ -0,0 +1,29 @@ +#include +#include +#include +#include +#include + +int main() { + std::atomic counter{0}; + constexpr int threadCount = 4; + constexpr int incrementsPerThread = 1'000; + + std::vector workers; + workers.reserve(static_cast(threadCount)); + + for (int i = 0; i < threadCount; ++i) { + workers.emplace_back([&counter]() { + for (int step = 0; step < incrementsPerThread; ++step) { + ++counter; + } + }); + } + + for (auto& worker : workers) { + worker.join(); + } + + std::cout << "counter: " << counter.load() << '\n'; + return 0; +} diff --git a/en/LEARNING_PATH.md b/en/LEARNING_PATH.md index db85791..5ea0abd 100644 --- a/en/LEARNING_PATH.md +++ b/en/LEARNING_PATH.md @@ -36,28 +36,52 @@ advanced topics too early. 18. `05_stl/README.md` 19. `05_stl/vector_algorithm_basics.cpp` -20. `10_templates/README.md` -21. `10_templates/template_repository.cpp` +20. `15_strings_views/README.md` +21. `15_strings_views/string_string_view.cpp` +22. `16_containers_iterators/README.md` +23. `16_containers_iterators/map_set_iterator.cpp` +24. `17_lambdas_algorithms/README.md` +25. `17_lambdas_algorithms/lambda_algorithm_pipeline.cpp` +26. `10_templates/README.md` +27. `10_templates/template_repository.cpp` ## Phase 6: Application Boundaries -22. `08_error_handling/README.md` -23. `08_error_handling/optional_exceptions_status.cpp` -24. `09_file_io/README.md` -25. `09_file_io/file_stream_records.cpp` +28. `08_error_handling/README.md` +29. `08_error_handling/optional_exceptions_status.cpp` +30. `09_file_io/README.md` +31. `09_file_io/file_stream_records.cpp` +32. `21_namespaces_headers/README.md` +33. `21_namespaces_headers/namespace_api_design.cpp` +34. `23_testing_practices/README.md` +35. `23_testing_practices/simple_test_harness.cpp` ## Phase 7: Systems And Architecture -26. `11_low_level_cpp/README.md` -27. `11_low_level_cpp/bytes_alignment_flags.cpp` -28. `12_concurrency/README.md` -29. `12_concurrency/thread_safe_counter.cpp` -30. `13_patterns_architecture/README.md` -31. `13_patterns_architecture/strategy_pattern.cpp` +36. `14_core_language_details/README.md` +37. `14_core_language_details/scope_enum_static.cpp` +38. `18_compile_time_constexpr/README.md` +39. `18_compile_time_constexpr/constexpr_lookup.cpp` +40. `19_variant_tuple_enum/README.md` +41. `19_variant_tuple_enum/variant_tuple_enum.cpp` +42. `20_operator_overloading/README.md` +43. `20_operator_overloading/value_type_operator.cpp` +44. `22_casts_type_safety/README.md` +45. `22_casts_type_safety/casts_type_safety.cpp` +46. `11_low_level_cpp/README.md` +47. `11_low_level_cpp/bytes_alignment_flags.cpp` +48. `24_filesystem_chrono/README.md` +49. `24_filesystem_chrono/filesystem_chrono.cpp` +50. `12_concurrency/README.md` +51. `12_concurrency/thread_safe_counter.cpp` +52. `25_atomics_intro/README.md` +53. `25_atomics_intro/atomic_counter.cpp` +54. `13_patterns_architecture/README.md` +55. `13_patterns_architecture/strategy_pattern.cpp` ## Phase 8: Project Practice -32. `projects/bank_account_oop/include/bank_account.h` -33. `projects/bank_account_oop/src/bank_account.cpp` -34. `projects/bank_account_oop/src/main.cpp` -35. `projects/bank_account_oop/tests/test_bank_account.cpp` +56. `projects/bank_account_oop/include/bank_account.h` +57. `projects/bank_account_oop/src/bank_account.cpp` +58. `projects/bank_account_oop/src/main.cpp` +59. `projects/bank_account_oop/tests/test_bank_account.cpp` diff --git a/en/README.md b/en/README.md index 5c09e3f..730cc41 100644 --- a/en/README.md +++ b/en/README.md @@ -23,6 +23,18 @@ and build discipline. - `11_low_level_cpp`: bytes, alignment, and flags. - `12_concurrency`: threads, mutexes, and shared state. - `13_patterns_architecture`: small design patterns and architecture decisions. +- `14_core_language_details`: scope, `enum class`, `static`, and state control. +- `15_strings_views`: `std::string`, `std::string_view`, and text lifetime. +- `16_containers_iterators`: map, set, iterator usage, and container choice. +- `17_lambdas_algorithms`: lambda captures and algorithm pipelines. +- `18_compile_time_constexpr`: `constexpr`, `static_assert`, compile-time data. +- `19_variant_tuple_enum`: `std::variant`, `std::tuple`, and alternative data. +- `20_operator_overloading`: operator design for value types. +- `21_namespaces_headers`: namespace and header API boundaries. +- `22_casts_type_safety`: explicit casts and type safety. +- `23_testing_practices`: deterministic tests and small test harnesses. +- `24_filesystem_chrono`: portable paths and type-safe time. +- `25_atomics_intro`: atomic counters and basic shared-state safety. - `projects/bank_account_oop`: modular OOP project with tests. ## How To Study diff --git a/en/REFERENCE_INDEX.md b/en/REFERENCE_INDEX.md index 4bb6d15..8ee7507 100644 --- a/en/REFERENCE_INDEX.md +++ b/en/REFERENCE_INDEX.md @@ -12,6 +12,18 @@ Use this file when you remember the problem but not the exact topic name. | Review RAII | `04_raii_memory/README.md` | | Pick a smart pointer | `06_smart_pointers/README.md` | | Understand move semantics | `07_move_semantics/README.md` | +| Review scope, `enum class`, or `static` | `14_core_language_details/README.md` | +| Use strings without needless copies | `15_strings_views/string_string_view.cpp` | +| Choose between map and set | `16_containers_iterators/README.md` | +| Write lambda predicates | `17_lambdas_algorithms/lambda_algorithm_pipeline.cpp` | +| Use `constexpr` or `static_assert` | `18_compile_time_constexpr/constexpr_lookup.cpp` | +| Model alternative data | `19_variant_tuple_enum/variant_tuple_enum.cpp` | +| Overload operators safely | `20_operator_overloading/value_type_operator.cpp` | +| Design namespace/header boundaries | `21_namespaces_headers/README.md` | +| Choose a C++ cast | `22_casts_type_safety/README.md` | +| Write simple tests | `23_testing_practices/simple_test_harness.cpp` | +| Use filesystem or chrono | `24_filesystem_chrono/filesystem_chrono.cpp` | +| Use a basic atomic counter | `25_atomics_intro/atomic_counter.cpp` | | Use `std::optional` | `08_error_handling/optional_exceptions_status.cpp` | | Read and write simple files | `09_file_io/file_stream_records.cpp` | | Write generic code | `10_templates/template_repository.cpp` | diff --git a/tr/14_core_language_details/README.md b/tr/14_core_language_details/README.md new file mode 100644 index 0000000..d1747d8 --- /dev/null +++ b/tr/14_core_language_details/README.md @@ -0,0 +1,23 @@ +# Core Language Detayları + +Küçük dil kuralları büyük C++ programlarının şeklini belirler. Scope, +`enum class`, `static`, `const` ve namespace kullanımı isimleri ve state'i +kontrol altında tutar. + +## Mental Model + +- Scope, bir ismin nerede görülebileceğini belirler. +- `enum class`, enum değerlerinin başka isimlerle çakışmasını azaltır. +- Local `static` değişken çağrılar arasında state saklar. +- Class `static` üyeleri tek bir objeye değil class'a aittir. +- Gizli global state yerine açık ownership ve açık parametreler tercih edilir. + +## Yaygın Hatalar + +- Unscoped `enum` değerleriyle isim çakışması oluşturmak. +- Class veya parametre daha netken global state kullanmak. +- `const` object state ile compile-time constant kavramını karıştırmak. + +## Örnek + +- `scope_enum_static.cpp`: scope, scoped enum ve class-level state gösterir. diff --git a/tr/14_core_language_details/scope_enum_static.cpp b/tr/14_core_language_details/scope_enum_static.cpp new file mode 100644 index 0000000..514326f --- /dev/null +++ b/tr/14_core_language_details/scope_enum_static.cpp @@ -0,0 +1,53 @@ +#include +#include + +enum class LogLevel { + info, + warning, + error, +}; + +std::string toString(const LogLevel level) { + switch (level) { + case LogLevel::info: + return "info"; + case LogLevel::warning: + return "warning"; + case LogLevel::error: + return "error"; + } + + return "unknown"; +} + +class Logger { +public: + explicit Logger(LogLevel minimumLevel) : minimumLevel_{minimumLevel} { + ++createdCount_; + } + + void print(LogLevel level, const std::string& message) const { + if (static_cast(level) >= static_cast(minimumLevel_)) { + std::cout << "[" << toString(level) << "] " << message << '\n'; + } + } + + static int createdCount() noexcept { + return createdCount_; + } + +private: + LogLevel minimumLevel_; + static int createdCount_; +}; + +int Logger::createdCount_ = 0; + +int main() { + Logger logger{LogLevel::warning}; + logger.print(LogLevel::info, "gizli"); + logger.print(LogLevel::error, "görünür"); + + std::cout << "logger sayısı: " << Logger::createdCount() << '\n'; + return 0; +} diff --git a/tr/15_strings_views/README.md b/tr/15_strings_views/README.md new file mode 100644 index 0000000..80e4b44 --- /dev/null +++ b/tr/15_strings_views/README.md @@ -0,0 +1,22 @@ +# String Ve View + +`std::string` metne sahip olur. `std::string_view` mevcut metni sahip olmadan +gözlemler. Bu farkı bilmek gereksiz copy ve dangling view hatalarını azaltır. + +## Mental Model + +- `std::string` karakterleri saklar ve sahiplenir. +- `std::string_view` mevcut karakterlere bakar, ownership almaz. +- Fonksiyon sadece okuyorsa ve view saklamıyorsa parametre için + `std::string_view` kullanılabilir. +- Local `std::string`e bakan `string_view` return etme. + +## Yaygın Hatalar + +- Orijinal string yok olduktan sonra `string_view` saklamak. +- `std::string` yeterliyken C-style string fonksiyonlarına dönmek. +- Copy gerekmeyen yerde büyük stringleri value ile geçirmek. + +## Örnek + +- `string_string_view.cpp`: metni copy etmeden trim ve prefix kontrolü yapar. diff --git a/tr/15_strings_views/string_string_view.cpp b/tr/15_strings_views/string_string_view.cpp new file mode 100644 index 0000000..3741761 --- /dev/null +++ b/tr/15_strings_views/string_string_view.cpp @@ -0,0 +1,29 @@ +#include +#include +#include + +std::string_view trimSpaces(std::string_view text) noexcept { + while (!text.empty() && text.front() == ' ') { + text.remove_prefix(1); + } + + while (!text.empty() && text.back() == ' ') { + text.remove_suffix(1); + } + + return text; +} + +bool startsWith(std::string_view text, std::string_view prefix) noexcept { + return text.size() >= prefix.size() && text.substr(0, prefix.size()) == prefix; +} + +int main() { + const std::string command{" upload:file.txt "}; + const std::string_view trimmed = trimSpaces(command); + + std::cout << "trimmed: " << trimmed << '\n'; + std::cout << "upload mı: " << std::boolalpha << startsWith(trimmed, "upload:") << '\n'; + + return 0; +} diff --git a/tr/16_containers_iterators/README.md b/tr/16_containers_iterators/README.md new file mode 100644 index 0000000..1534381 --- /dev/null +++ b/tr/16_containers_iterators/README.md @@ -0,0 +1,22 @@ +# Container Ve Iterator + +STL containerları farklı saklama ve lookup problemlerini çözer. Iteratorlar, +algorithmlerin birçok container ile çalışmasını sağlayan ortak erişim modelidir. + +## Mental Model + +- `std::vector` varsayılan sequence container olarak düşünülebilir. +- `std::map` keyleri sıralı tutar. +- `std::unordered_map` ortalama lookup süresini hash ile optimize eder. +- `std::set` unique ve sıralı değer saklar. +- Iteratorlar container içine bakar; invalidation kuralları önemlidir. + +## Yaygın Hatalar + +- Hash lookup yeterliyken `map` seçmek. +- Silme işlemi sonrası invalid iterator kullanmak. +- Lookup ve iteration ihtiyacını düşünmeden container seçmek. + +## Örnek + +- `map_set_iterator.cpp`: frequency table kurar ve sıralı unique key çıkarır. diff --git a/tr/16_containers_iterators/map_set_iterator.cpp b/tr/16_containers_iterators/map_set_iterator.cpp new file mode 100644 index 0000000..258e5e9 --- /dev/null +++ b/tr/16_containers_iterators/map_set_iterator.cpp @@ -0,0 +1,31 @@ +#include +#include +#include +#include +#include + +int main() { + const std::vector tags{ + "cpp", + "systems", + "cpp", + "oop", + "systems", + "templates", + }; + + std::map frequencies; + std::set uniqueTags; + + for (const auto& tag : tags) { + ++frequencies[tag]; + uniqueTags.insert(tag); + } + + for (auto it = frequencies.begin(); it != frequencies.end(); ++it) { + std::cout << it->first << " -> " << it->second << '\n'; + } + + std::cout << "unique tag sayısı: " << uniqueTags.size() << '\n'; + return 0; +} diff --git a/tr/17_lambdas_algorithms/README.md b/tr/17_lambdas_algorithms/README.md new file mode 100644 index 0000000..3049f32 --- /dev/null +++ b/tr/17_lambdas_algorithms/README.md @@ -0,0 +1,23 @@ +# Lambda Ve Algorithm + +Lambdalar davranışı kullanan algorithmin yanında tutmayı sağlar. En faydalı +halleri standard algorithmlerle birlikte kullanıldığında ortaya çıkar. + +## Mental Model + +- `[]` capture listesidir. +- `[value]` value ile capture eder. +- `[&value]` reference ile capture eder. +- Niyeti daha net anlatıyorsa standard algorithm tercih edilir. +- Lambda uzuyorsa named function daha iyi olabilir. + +## Yaygın Hatalar + +- Referans capture edilen nesneden daha uzun yaşayan lambda tutmak. +- Uzun lambda yazıp okunabilirliği düşürmek. +- Basit range-for daha netken `for_each` kullanmak. + +## Örnek + +- `lambda_algorithm_pipeline.cpp`: lambda ve algorithm ile filtreleme, + dönüştürme ve toplama yapar. diff --git a/tr/17_lambdas_algorithms/lambda_algorithm_pipeline.cpp b/tr/17_lambdas_algorithms/lambda_algorithm_pipeline.cpp new file mode 100644 index 0000000..c65f96a --- /dev/null +++ b/tr/17_lambdas_algorithms/lambda_algorithm_pipeline.cpp @@ -0,0 +1,40 @@ +#include +#include +#include +#include +#include + +struct Order { + std::string customer; + double total; +}; + +int main() { + std::vector orders{ + {"Ada", 120.0}, + {"Bjarne", 80.0}, + {"Grace", 210.0}, + }; + + const double minimum = 100.0; + const auto isLargeOrder = [minimum](const Order& order) { + return order.total >= minimum; + }; + + std::vector largeTotals; + for (const auto& order : orders) { + if (isLargeOrder(order)) { + largeTotals.push_back(order.total); + } + } + + std::transform(largeTotals.begin(), largeTotals.end(), largeTotals.begin(), [](double total) { + return total * 1.20; + }); + + const double sum = std::accumulate(largeTotals.begin(), largeTotals.end(), 0.0); + + std::cout << "büyük sipariş sayısı: " << largeTotals.size() << '\n'; + std::cout << "vergili toplam: " << sum << '\n'; + return 0; +} diff --git a/tr/18_compile_time_constexpr/README.md b/tr/18_compile_time_constexpr/README.md new file mode 100644 index 0000000..47789bf --- /dev/null +++ b/tr/18_compile_time_constexpr/README.md @@ -0,0 +1,23 @@ +# Compile-Time Ve Constexpr + +C++ bazı değerleri compile time'da hesaplayabilir. Girdiler erkenden biliniyorsa +bu hem güvenliği artırır hem runtime işi azaltabilir. + +## Mental Model + +- `const`, o isim üzerinden değerin değiştirilemeyeceğini söyler. +- `constexpr`, değer veya fonksiyonun compile-time evaluation'a katılabileceğini + söyler. +- `static_assert`, koşulu derleme sırasında kontrol eder. +- Compile-time kod da okunabilir kalmalıdır. + +## Yaygın Hatalar + +- Her `const` değeri compile-time sanmak. +- Gerekmeyen yere `constexpr` zorlamak. +- Karmaşık runtime logic'i compile-time numaraya çevirmek. + +## Örnek + +- `constexpr_lookup.cpp`: küçük lookup değerlerini hesaplar ve `static_assert` + ile doğrular. diff --git a/tr/18_compile_time_constexpr/constexpr_lookup.cpp b/tr/18_compile_time_constexpr/constexpr_lookup.cpp new file mode 100644 index 0000000..716040b --- /dev/null +++ b/tr/18_compile_time_constexpr/constexpr_lookup.cpp @@ -0,0 +1,21 @@ +#include +#include + +constexpr int square(const int value) noexcept { + return value * value; +} + +constexpr std::array makeSquares() { + return {square(0), square(1), square(2), square(3), square(4)}; +} + +int main() { + constexpr auto squares = makeSquares(); + static_assert(squares[4] == 16, "square table hatalı"); + + for (const int value : squares) { + std::cout << value << '\n'; + } + + return 0; +} diff --git a/tr/19_variant_tuple_enum/README.md b/tr/19_variant_tuple_enum/README.md new file mode 100644 index 0000000..232eb78 --- /dev/null +++ b/tr/19_variant_tuple_enum/README.md @@ -0,0 +1,22 @@ +# Variant, Tuple Ve Enum + +Bazı veriler birkaç bilinen alternatiften biri olabilir. C++17, type-safe +alternatifler için `std::variant`, sabit değer grupları için `std::tuple` verir. + +## Mental Model + +- `enum class`, kapalı bir state seti isimlendirir. +- `std::variant`, listelenen tiplerden tam olarak birini saklar. +- `std::visit`, aktif variant alternatifini işler. +- `std::tuple`, küçük ve sabit değer gruplarını saklar. +- Field isimleri önemliyse tuple yerine named struct tercih edilir. + +## Yaygın Hatalar + +- Alternatif modellemek için gereksiz inheritance kullanmak. +- Field isimleri gerekirken tuple ile okunabilirliği düşürmek. +- Variant alternatiflerinden birini handle etmeyi unutmak. + +## Örnek + +- `variant_tuple_enum.cpp`: mesajları bilinen alternatifler olarak modeller. diff --git a/tr/19_variant_tuple_enum/variant_tuple_enum.cpp b/tr/19_variant_tuple_enum/variant_tuple_enum.cpp new file mode 100644 index 0000000..2b9cd47 --- /dev/null +++ b/tr/19_variant_tuple_enum/variant_tuple_enum.cpp @@ -0,0 +1,35 @@ +#include +#include +#include +#include + +struct LoginEvent { + std::string user; +}; + +struct ErrorEvent { + int code; + std::string message; +}; + +using Event = std::variant; + +struct EventPrinter { + void operator()(const LoginEvent& event) const { + std::cout << "login: " << event.user << '\n'; + } + + void operator()(const ErrorEvent& event) const { + std::cout << "error " << event.code << ": " << event.message << '\n'; + } +}; + +int main() { + const Event event = ErrorEvent{404, "not found"}; + std::visit(EventPrinter{}, event); + + const std::tuple summary{1, "processed"}; + std::cout << std::get<0>(summary) << " -> " << std::get<1>(summary) << '\n'; + + return 0; +} diff --git a/tr/20_operator_overloading/README.md b/tr/20_operator_overloading/README.md new file mode 100644 index 0000000..8500caf --- /dev/null +++ b/tr/20_operator_overloading/README.md @@ -0,0 +1,21 @@ +# Operator Overloading + +Operator overloading, value type'ların doğal kullanılmasını sağlar. Pahalı iş +veya beklenmedik side effect saklamak için kullanılmamalıdır. + +## Mental Model + +- Money, vector, id gibi value type'larda operator mantıklıdır. +- Operator davranışı normal beklentiyle uyumlu olmalıdır. +- Domain-specific işler için named function daha okunabilir olabilir. +- Gerekliyse önce compound assignment yazılır, binary operator ondan türetilir. + +## Yaygın Hatalar + +- Sadece havalı syntax için operator overload etmek. +- `operator+` içinde sol objeyi değiştirmek. +- `const` correctness unutmak. + +## Örnek + +- `value_type_operator.cpp`: küçük bir `Money` value type'ı uygular. diff --git a/tr/20_operator_overloading/value_type_operator.cpp b/tr/20_operator_overloading/value_type_operator.cpp new file mode 100644 index 0000000..96b2296 --- /dev/null +++ b/tr/20_operator_overloading/value_type_operator.cpp @@ -0,0 +1,42 @@ +#include +#include + +class Money { +public: + explicit Money(int cents) : cents_{cents} {} + + int cents() const noexcept { + return cents_; + } + + Money& operator+=(const Money other) noexcept { + cents_ += other.cents_; + return *this; + } + +private: + int cents_; +}; + +Money operator+(Money lhs, const Money rhs) noexcept { + lhs += rhs; + return lhs; +} + +bool operator==(const Money lhs, const Money rhs) noexcept { + return lhs.cents() == rhs.cents(); +} + +std::ostream& operator<<(std::ostream& output, const Money money) { + return output << money.cents() / 100 << "." << money.cents() % 100; +} + +int main() { + const Money salary{125'000}; + const Money bonus{25'000}; + const Money total = salary + bonus; + + std::cout << "toplam: " << total << '\n'; + std::cout << "beklenenle aynı: " << std::boolalpha << (total == Money{150'000}) << '\n'; + return 0; +} diff --git a/tr/21_namespaces_headers/README.md b/tr/21_namespaces_headers/README.md new file mode 100644 index 0000000..3cd9252 --- /dev/null +++ b/tr/21_namespaces_headers/README.md @@ -0,0 +1,22 @@ +# Namespace Ve Header Tasarımı + +Büyük C++ projelerinde sınırlar gerekir. Namespace ve header dosyaları, her +implementation detayını açmadan API görünürlüğü sağlar. + +## Mental Model + +- Header public interface bildirir. +- Source file implementation detaylarını tanımlar. +- Namespace isim çakışmalarını önler. +- Header küçük tutulmalıdır çünkü her include compile time'ı etkiler. +- Dolaylı include'a güvenmek yerine kullandığın şeyi include et. + +## Yaygın Hatalar + +- Header içinde `using namespace std;` yazmak. +- Private helper fonksiyonları public header'a koymak. +- Forward declaration yeterliyken ağır header include etmek. + +## Örnek + +- `namespace_api_design.cpp`: tek dosyada küçük namespaced API tasarımı gösterir. diff --git a/tr/21_namespaces_headers/namespace_api_design.cpp b/tr/21_namespaces_headers/namespace_api_design.cpp new file mode 100644 index 0000000..ee81a43 --- /dev/null +++ b/tr/21_namespaces_headers/namespace_api_design.cpp @@ -0,0 +1,33 @@ +#include +#include +#include + +namespace telemetry { +class Reading { +public: + Reading(std::string name, double value) : name_{std::move(name)}, value_{value} {} + + const std::string& name() const noexcept { + return name_; + } + + double value() const noexcept { + return value_; + } + +private: + std::string name_; + double value_; +}; + +std::string format(const Reading& reading) { + return reading.name() + "=" + std::to_string(reading.value()); +} +} // namespace telemetry + +int main() { + const telemetry::Reading reading{"temperature", 24.5}; + std::cout << telemetry::format(reading) << '\n'; + + return 0; +} diff --git a/tr/22_casts_type_safety/README.md b/tr/22_casts_type_safety/README.md new file mode 100644 index 0000000..f139735 --- /dev/null +++ b/tr/22_casts_type_safety/README.md @@ -0,0 +1,23 @@ +# Cast Ve Type Safety + +C++ castleri görünür ve bilinçli olmalıdır. Bir cast çoğu zaman programın iki +parçasının tipler konusunda anlaşamadığını gösterir. + +## Mental Model + +- `static_cast`, compile-time kontrol edilebilen dönüşümler içindir. +- `dynamic_cast`, polymorphic base üzerinden güvenli downcast içindir. +- `const_cast`, constness değiştirir ve nadir kullanılmalıdır. +- `reinterpret_cast`, bitleri başka tip gibi yorumlar ve low-level sınırlarda + kalmalıdır. +- Cast gerektirmeyen API tasarımı genelde daha iyidir. + +## Yaygın Hatalar + +- Kısa diye C-style cast kullanmak. +- Virtual function daha temizken downcast yapmak. +- Range kontrolü olmadan daraltıcı numeric cast yapmak. + +## Örnek + +- `casts_type_safety.cpp`: numeric cast ve güvenli polymorphic downcast gösterir. diff --git a/tr/22_casts_type_safety/casts_type_safety.cpp b/tr/22_casts_type_safety/casts_type_safety.cpp new file mode 100644 index 0000000..1ff4c16 --- /dev/null +++ b/tr/22_casts_type_safety/casts_type_safety.cpp @@ -0,0 +1,27 @@ +#include +#include + +class Device { +public: + virtual ~Device() = default; +}; + +class SensorDevice final : public Device { +public: + int sample() const noexcept { + return 42; + } +}; + +int main() { + const double rawValue = 42.9; + const int roundedDown = static_cast(rawValue); + std::cout << "aşağı yuvarlandı: " << roundedDown << '\n'; + + std::unique_ptr device = std::make_unique(); + if (const auto* sensor = dynamic_cast(device.get())) { + std::cout << "sample: " << sensor->sample() << '\n'; + } + + return 0; +} diff --git a/tr/23_testing_practices/README.md b/tr/23_testing_practices/README.md new file mode 100644 index 0000000..6fe0fe7 --- /dev/null +++ b/tr/23_testing_practices/README.md @@ -0,0 +1,23 @@ +# Test Pratikleri + +Testler refactor sırasında davranışı korur. Küçük bir test harness bile her +seferinde programı manuel çalıştırıp çıktıya bakmaktan iyidir. + +## Mental Model + +- Private implementation değil observable behavior test edilir. +- Testler deterministic olmalıdır. +- Edge case ve failure path test edilir. +- Başarısız test build'i durdurmalıdır. +- Gerçek projelerde test framework kullanılır; öğrenme örneklerinde küçük helper + yeterli olabilir. + +## Yaygın Hatalar + +- Sadece happy path test etmek. +- Test çalışma sırasına bağımlı olmak. +- Hata yazdırıp yine success return etmek. + +## Örnek + +- `simple_test_harness.cpp`: framework kullanmadan küçük test runner gösterir. diff --git a/tr/23_testing_practices/simple_test_harness.cpp b/tr/23_testing_practices/simple_test_harness.cpp new file mode 100644 index 0000000..fe1e409 --- /dev/null +++ b/tr/23_testing_practices/simple_test_harness.cpp @@ -0,0 +1,39 @@ +#include +#include +#include +#include +#include + +int clamp(const int value, const int low, const int high) { + if (low > high) { + throw std::invalid_argument{"low high değerinden büyük olamaz"}; + } + if (value < low) { + return low; + } + if (value > high) { + return high; + } + return value; +} + +void require(const bool condition, const std::string& message) { + if (!condition) { + throw std::runtime_error{message}; + } +} + +int main() { + const std::vector> tests{ + {"değer aralık içinde", []() { require(clamp(5, 1, 10) == 5, "inside range failed"); }}, + {"değer aralık altında", []() { require(clamp(-1, 1, 10) == 1, "below range failed"); }}, + {"değer aralık üstünde", []() { require(clamp(99, 1, 10) == 10, "above range failed"); }}, + }; + + for (const auto& test : tests) { + test.second(); + std::cout << "geçti: " << test.first << '\n'; + } + + return 0; +} diff --git a/tr/24_filesystem_chrono/README.md b/tr/24_filesystem_chrono/README.md new file mode 100644 index 0000000..f6c6e0e --- /dev/null +++ b/tr/24_filesystem_chrono/README.md @@ -0,0 +1,21 @@ +# Filesystem Ve Chrono + +C++17 standart filesystem desteği getirdi. `std::chrono` ise type-safe süre ve +zaman noktası kullanımı sağlar. + +## Mental Model + +- `std::filesystem::path`, path bilgisini taşınabilir şekilde temsil eder. +- Path stringlerini elle birleştirmek yerine filesystem fonksiyonları kullanılır. +- `std::chrono::duration`, süre miktarını temsil eder. +- `std::chrono::time_point`, zamandaki bir noktayı temsil eder. + +## Yaygın Hatalar + +- Pathleri raw string concatenation ile kurmak. +- Milisaniye ve saniyeyi düz integer olarak karıştırmak. +- Path separator'ın her işletim sisteminde aynı olduğunu varsaymak. + +## Örnek + +- `filesystem_chrono.cpp`: path oluşturur ve küçük bir işlemin süresini ölçer. diff --git a/tr/24_filesystem_chrono/filesystem_chrono.cpp b/tr/24_filesystem_chrono/filesystem_chrono.cpp new file mode 100644 index 0000000..28741e2 --- /dev/null +++ b/tr/24_filesystem_chrono/filesystem_chrono.cpp @@ -0,0 +1,22 @@ +#include +#include +#include +#include +#include + +int main() { + const std::filesystem::path base{"build"}; + const std::filesystem::path report = base / "report.txt"; + + const auto start = std::chrono::steady_clock::now(); + const std::vector values{1, 2, 3, 4, 5}; + const int sum = std::accumulate(values.begin(), values.end(), 0); + const auto end = std::chrono::steady_clock::now(); + + const auto elapsed = std::chrono::duration_cast(end - start); + + std::cout << "report path: " << report.string() << '\n'; + std::cout << "toplam: " << sum << '\n'; + std::cout << "geçen mikrosaniye: " << elapsed.count() << '\n'; + return 0; +} diff --git a/tr/25_atomics_intro/README.md b/tr/25_atomics_intro/README.md new file mode 100644 index 0000000..1529736 --- /dev/null +++ b/tr/25_atomics_intro/README.md @@ -0,0 +1,22 @@ +# Atomic Giriş + +Atomicler basit shared değerlerin mutex olmadan güncellenmesini sağlar. Güçlüdür +ama thread ownership ve invariant bilgisi yerine geçmez. + +## Mental Model + +- `std::atomic`, `T` üzerindeki işlemleri atomic hale getirir. +- Atomic counter basittir; lock-free algorithm ileri konudur. +- Birden fazla alandan oluşan state ve invariant için mutex daha uygundur. +- Zayıf memory order öğrenmeden önce default sequentially consistent davranışla + başlamak daha güvenlidir. + +## Yaygın Hatalar + +- Atomic kullanınca tüm object thread-safe oldu sanmak. +- Aynı değere hem atomic hem non-atomic erişmek. +- Kanıt olmadan relaxed memory ordering kullanmak. + +## Örnek + +- `atomic_counter.cpp`: shared atomic counter'ı birden fazla thread'den artırır. diff --git a/tr/25_atomics_intro/atomic_counter.cpp b/tr/25_atomics_intro/atomic_counter.cpp new file mode 100644 index 0000000..493e202 --- /dev/null +++ b/tr/25_atomics_intro/atomic_counter.cpp @@ -0,0 +1,29 @@ +#include +#include +#include +#include +#include + +int main() { + std::atomic counter{0}; + constexpr int threadCount = 4; + constexpr int incrementsPerThread = 1'000; + + std::vector workers; + workers.reserve(static_cast(threadCount)); + + for (int i = 0; i < threadCount; ++i) { + workers.emplace_back([&counter]() { + for (int step = 0; step < incrementsPerThread; ++step) { + ++counter; + } + }); + } + + for (auto& worker : workers) { + worker.join(); + } + + std::cout << "counter: " << counter.load() << '\n'; + return 0; +} diff --git a/tr/LEARNING_PATH.md b/tr/LEARNING_PATH.md index 4e8061e..93a29e4 100644 --- a/tr/LEARNING_PATH.md +++ b/tr/LEARNING_PATH.md @@ -36,28 +36,52 @@ tasarlandı. 18. `05_stl/README.md` 19. `05_stl/vector_algorithm_basics.cpp` -20. `10_templates/README.md` -21. `10_templates/template_repository.cpp` +20. `15_strings_views/README.md` +21. `15_strings_views/string_string_view.cpp` +22. `16_containers_iterators/README.md` +23. `16_containers_iterators/map_set_iterator.cpp` +24. `17_lambdas_algorithms/README.md` +25. `17_lambdas_algorithms/lambda_algorithm_pipeline.cpp` +26. `10_templates/README.md` +27. `10_templates/template_repository.cpp` ## Faz 6: Uygulama Sınırları -22. `08_error_handling/README.md` -23. `08_error_handling/optional_exceptions_status.cpp` -24. `09_file_io/README.md` -25. `09_file_io/file_stream_records.cpp` +28. `08_error_handling/README.md` +29. `08_error_handling/optional_exceptions_status.cpp` +30. `09_file_io/README.md` +31. `09_file_io/file_stream_records.cpp` +32. `21_namespaces_headers/README.md` +33. `21_namespaces_headers/namespace_api_design.cpp` +34. `23_testing_practices/README.md` +35. `23_testing_practices/simple_test_harness.cpp` ## Faz 7: Systems Ve Architecture -26. `11_low_level_cpp/README.md` -27. `11_low_level_cpp/bytes_alignment_flags.cpp` -28. `12_concurrency/README.md` -29. `12_concurrency/thread_safe_counter.cpp` -30. `13_patterns_architecture/README.md` -31. `13_patterns_architecture/strategy_pattern.cpp` +36. `14_core_language_details/README.md` +37. `14_core_language_details/scope_enum_static.cpp` +38. `18_compile_time_constexpr/README.md` +39. `18_compile_time_constexpr/constexpr_lookup.cpp` +40. `19_variant_tuple_enum/README.md` +41. `19_variant_tuple_enum/variant_tuple_enum.cpp` +42. `20_operator_overloading/README.md` +43. `20_operator_overloading/value_type_operator.cpp` +44. `22_casts_type_safety/README.md` +45. `22_casts_type_safety/casts_type_safety.cpp` +46. `11_low_level_cpp/README.md` +47. `11_low_level_cpp/bytes_alignment_flags.cpp` +48. `24_filesystem_chrono/README.md` +49. `24_filesystem_chrono/filesystem_chrono.cpp` +50. `12_concurrency/README.md` +51. `12_concurrency/thread_safe_counter.cpp` +52. `25_atomics_intro/README.md` +53. `25_atomics_intro/atomic_counter.cpp` +54. `13_patterns_architecture/README.md` +55. `13_patterns_architecture/strategy_pattern.cpp` ## Faz 8: Proje Pratiği -32. `projects/bank_account_oop/include/bank_account.h` -33. `projects/bank_account_oop/src/bank_account.cpp` -34. `projects/bank_account_oop/src/main.cpp` -35. `projects/bank_account_oop/tests/test_bank_account.cpp` +56. `projects/bank_account_oop/include/bank_account.h` +57. `projects/bank_account_oop/src/bank_account.cpp` +58. `projects/bank_account_oop/src/main.cpp` +59. `projects/bank_account_oop/tests/test_bank_account.cpp` diff --git a/tr/README.md b/tr/README.md index 7a9cbf2..3db986a 100644 --- a/tr/README.md +++ b/tr/README.md @@ -22,6 +22,18 @@ düzenini birlikte öğrenmektir. - `11_low_level_cpp`: byte, alignment ve flag mantığı. - `12_concurrency`: thread, mutex ve shared state. - `13_patterns_architecture`: küçük pattern ve architecture kararları. +- `14_core_language_details`: scope, `enum class`, `static` ve state kontrolü. +- `15_strings_views`: `std::string`, `std::string_view` ve text lifetime. +- `16_containers_iterators`: map, set, iterator ve container seçimi. +- `17_lambdas_algorithms`: lambda capture ve algorithm pipeline. +- `18_compile_time_constexpr`: `constexpr`, `static_assert`, compile-time veri. +- `19_variant_tuple_enum`: `std::variant`, `std::tuple` ve alternatif veri. +- `20_operator_overloading`: value type için operator tasarımı. +- `21_namespaces_headers`: namespace ve header API sınırları. +- `22_casts_type_safety`: explicit castler ve type safety. +- `23_testing_practices`: deterministic test ve küçük test harness. +- `24_filesystem_chrono`: taşınabilir path ve type-safe zaman. +- `25_atomics_intro`: atomic counter ve temel shared-state güvenliği. - `projects/bank_account_oop`: testli modüler OOP projesi. ## Nasıl Çalışılır? diff --git a/tr/REFERENCE_INDEX.md b/tr/REFERENCE_INDEX.md index 1dfc54a..58b8ccc 100644 --- a/tr/REFERENCE_INDEX.md +++ b/tr/REFERENCE_INDEX.md @@ -12,6 +12,18 @@ Problemi hatırlayıp konu adını hatırlamadığında buradan hızlıca git. | RAII hatırlamak | `04_raii_memory/README.md` | | Smart pointer seçmek | `06_smart_pointers/README.md` | | Move semantics anlamak | `07_move_semantics/README.md` | +| Scope, `enum class` veya `static` bakmak | `14_core_language_details/README.md` | +| Gereksiz copy olmadan string kullanmak | `15_strings_views/string_string_view.cpp` | +| Map ve set seçimi yapmak | `16_containers_iterators/README.md` | +| Lambda predicate yazmak | `17_lambdas_algorithms/lambda_algorithm_pipeline.cpp` | +| `constexpr` veya `static_assert` kullanmak | `18_compile_time_constexpr/constexpr_lookup.cpp` | +| Alternatif veri modellemek | `19_variant_tuple_enum/variant_tuple_enum.cpp` | +| Operator overload etmek | `20_operator_overloading/value_type_operator.cpp` | +| Namespace/header sınırı tasarlamak | `21_namespaces_headers/README.md` | +| C++ cast seçmek | `22_casts_type_safety/README.md` | +| Basit test yazmak | `23_testing_practices/simple_test_harness.cpp` | +| Filesystem veya chrono kullanmak | `24_filesystem_chrono/filesystem_chrono.cpp` | +| Basit atomic counter kullanmak | `25_atomics_intro/atomic_counter.cpp` | | `std::optional` kullanmak | `08_error_handling/optional_exceptions_status.cpp` | | Basit dosya okuyup yazmak | `09_file_io/file_stream_records.cpp` | | Generic code yazmak | `10_templates/template_repository.cpp` |