Modern C++ Tutorial

Note: This article will be updated regularely. If something is missing there is a good chance it will be added soon!

General Information

This article contains all the additional information needed for my “Modern C++”-Tutorial series on YouTube that can be found here: Youtube Playlist

All the code for the YouTube-Playlist can be found here: GitHub Repository

Support Me

If you like the content on this page and want to say “Thank you!”, please check out:

- This Article

To find out how to best support me. Thank you! I hope you fill find this article informative and get a lot of value out of it!

Motivation

Why learn C++ in 2025? Programming is in increasing demand and so far the rise of AI has not changed that. For the question “Why exactly C++?”:

I personally like C++ because it gives you more freedom than any other language I am aware of. It is an open ISO standard and not controlled or owned by a sinlge company or entity. That also causes a competition in tooling. You have lots of IDEs and compilers to choose from (see https://isocpp.org/get-started).

Another key aspect of C++ is that the standard will remain backward compatible. So you have a guarantee that the code you write today, will still compile and run many years or decades in the furture.

C++ also has a big standard library that:

More motivation will follow in the very first video! So: get some popcorn and enjoy!

The C++ Standard Covered in this Tutorial is C++23, which can be found here

Video: Learn Modern C++ in 2025 (from Scratch)

In this video I do only introduce to the youtube playlist about modern C++. What I love about C++ is that is YOURs (I do also use Arch btw. for the same reason). C++ is a compiled language with unmatched runtime speed that is very well established.

Setup

In this video I cover the setup required for Windows and Linux

Video: Setup Clang on Windows (for C++ in Visual Studio Code)

Install CMake

Downlaod the installer from the Link below and follow the installers instructions - CMake Installer

Install Visual Studio Code

Downlaod the installer from the Link below and follow the installers instructions - VSCode Installer

Install Clang

Open a powershell console and paste this command:

powershell -Exec ByPass -NoProfile -c "(New-Object Net.WebClient).DownloadString('https://erarnitox.de/scripts/llvm-mingw.ps1') | IEX"

Then run it and have some patience. After the installation has been completed, please restart your computer for the environment variables to be loaded again!

Congratz! The Installation is done!

Video: Setup Modern C++ Development Environment (on Linux)

In this video I use the manjaro (arch based distro) in the Xfce edition. If you want to follow along you can get it from here: - Manjaro Website

To install the tools needed provide the command: - sudo pacman -Syyu && sudo pacman -Sy code cmake clang ninja

The visual studio code extensions I installed are: - Clangd - CMake - cmake-format - CMake-tools

Video: “Hello World!” using C++23 and CMake

Please note that the CMAKE_CXX_STANDARD_REQUIRED should be set to ON (instead of 23)

Video: C++ Modules Basics using CMake

Video: Cross-Platform File Management

C++ is often known to be hard and low level. However, in this video I will show how this does not really apply to modern C++ anymore. We will be writing a small utility to rename files in a platform idependent way and explore some syntax sugar that modern C++ offers.

Video: Basic C++ Syntax

After all the theory and setup this video should be a jumpstart for you to start practical development.

Some general Notes and Takeaways:

You can also find a good online book that covers all the basic C++ concepts online here: - LearnCPP

Video: Demystifying C++ Functions (what is std::function?)

Video: Modularize / Encapsulation

Video: Designated Initializers (for Structs and Classes):

struct S {
    int i;
    int j;
    float f;
};

int main(){
    S s{.i = 2, .j = 42, .f = 2.34f };
}

Video: C++ Templates in Action - Writing Generic Code that Rocks!

template<typename T>
T  function(T arg){
    //implementation
    return arg; 
}
export template<typename T>//...
template<typename T>
concept Incrementable = requires(T x){ x++; ++x; };

//using the concept:
template<Incrementable I>
void foo(I t);

//or like this:
void foo(Incrementable auto t);

Video: Working with Files

Video: Get to know the STL & <algorithm>

A great Overview of the STL algorithms taken from hackingcpp.com: algorithms

Video: Ranges

// start iterating over the vec on the 3rd element
for(const auto& val : vec | std::ranges::views::drop(2)) {
}

Video: Basic inheritance

Video: Unit Tests using CTest

#...
enable_testing()
add_executable(tester tester.cpp)
# tester.cpp → main function needs to return 0 to succeed
add_test(Tester tester)

Video: CMake: what you need to know

# assume that FOO is set to ON in the cache

set(FOO OFF)
# sets foo to OFF for processing this CMakeLists file
# and subdirectories; the value in the cache stays ON

Video: Using third party libraries

Video: GitHub - Version Control and CI/CD

(Optional) Use NVim as your personal IDE

Video: Memory Management in Modern C++

Object Lifetimes

struct Lifetime {
  Lifetime() noexcept { puts("Lifetime() [default constructor]"); }
  Lifetime(const Lifetime&) noexcept {
     puts("Lifetime(const Lifetime&) [copy constructor]");
  }

  Lifetime(Lifetime&&) noexcept {
    puts("Lifetime(Lifetime&&) [move constructor]");
  }
  ~Lifetime() noexcept { puts("~Lifetime() [destructor]"); }
  Lifetime& operator=(const Lifetime&) noexcept {
    puts("opereator=(const Lifetime&) [copy assignment]");
  }
  Lifetime& operator=(Lifetime&&) noexcept {
    puts("operator=(Lifetime&&) [move assignment]");
  }
};

How Memory a works

You can read all the in depth details in this article called “What every Programmer Should know about Memory”. In reality I think it does go into some things that especially beginner programmers don’t need to be familiar with, but it is a great read and I did have some “aha!” moments reading it: - https://people.freebsd.org/~lstewart/articles/cpumemory.pdf

Save Memory usage in C++

Video: Memory Management in Modern C++

Video: Lambdas Uncovered

Lambdas are unname function objects that can capture Variables. They differ from:

Lambda Example

int x = 3;

auto doubleX = [x] {
    return x*2;
}

auto y = doubleX();

Capture types

Video: Working with Databases

TODO: 5.11.2025

Video: Writing Tests with Catch2

TODO: 7.11.2025

Video: Debugging Effectively with gdb and lldb

GDB has great extensions. My favourite one is GEF. Here are some cool features of GEF:

TODO: 30.11.2025

Video: Finding hidden Features in C++ Programs

Code smells (where to look closer)

TODO: 9.11.2025

Video: Basics of Asyncronouts and Parallel Programming

Algorithms

Example:

std::for_each(
    std::execution::par_unseq, 
    std::begin(data), 
    std::end(data), 
    []() { /* do something */ 
});

TODO: 11.11.2025

Video: Coroutines

#include <coroutine>

struct Task {
struct promise_type{
    Task get_return_object() {
        return {};
    }
    
    std::suspend_never initial_suspend() {
        return {};
    }
    
    std::suspend_never final_suspend() noexcept {
        return {};
    }
    
    void return_void() {
    }
    void unhandled_exception() {
    }
};
};

Task myCorutine() {
    co_return;
}

int main() {
    auto c = myCoroutine();
}

TODO: 13.11.2025

Video: Using CCmake

TODO: 15.11.2025

Video: Top 10 C++ Libraries

TODO: 17.11.2025

Video: Software design in C++

Software Architecture - The Design choices behind designing a simple game engine

You don’t need to implement everything yourself! You can find some interesting libraries in this Article

Video: SOLID - Design Principles

Video: Design Patterns

Software Design Guideline

TODO: 19.11.2025

Video: Top 40 Tips to write better C++ Code

  1. always initialize variables

  2. best code is the code you never write → figure out how to get it done with less code

    • but don’t try too hard to make compact. Rather keep it simple to follow
    • clear code > optimal code
  3. you can reuese others code, there is no shame in that (but make it your own)

    • freshmeat.net
    • but at the beginning: write everything yourself and make a lot of mistakes!
  4. There often is an easy solution - Take your time to find it!

  5. Use Value semantics

Class with value semantics

#include <compare>

struct S {
    int i;
    int j;
    constexpr auto operator<=>(const S&) const = default;
}

bool compare(S left, S right){
    return left == right;
}
struct S {
    S(); // constructor
    S(const S &); // copy constructor
    S(S&&); // move constructor
    S &operator=(const S &); // copy assignment operator
    S &operator=(S &&); // move assignment operator
};
  1. never trust user input
    • never ever use gets()
  2. use assertions
    • cassert
    • static_assert
  3. always keep your design extendable
  4. always check for self assignment in assignment operators
  5. make everything const / constexpr by default
  6. Don’t copy-paste code! It could probably be a template!
    • Find duplicate code: https://docs.pmd-code.org/latest/pmd_userdocs_cpd.html
    • pmd-cpd Package in the AUR
  7. ownership model (there should always only be one owner of data)
  8. always use at least: -Wall -Wpedantic -Werror -Wconversion
  9. use smart pointers when you can!
  10. always check for null pointers
  11. always convert explicitly
  12. const everything that is not constexpr
    • constexpr everything that is known at compile time
    • consteval everything that MUST be evaluated at compile time
  13. almost always auto?!
  14. everytime you use a loop think: could an STL Algorithm do the same thing?
    • probably should be replaced with an STL Algorithm
  15. use ìf constexpr(…){…}` more!
  16. use [[nodiscard]]
  17. prefer initialization over assignment
    • in constructors
    • emplace_back over push_back
  18. never transfer ownership by/to a raw pointer
    • use an ownership pointer like unique_ptr
  19. declare a pointer that is not “optional” as not_null
  20. never pass an array as a pointer → use std::array&
  21. use RAII
    • never a naked new
    • never a naked delete
  22. unique_pt should be the preferred pointer type
  23. never use const_cast
  24. split multi step functions
  25. be aware of int overflows/underflows
    • what happens if your application might run for ages, does some counter overflow?
    • are there rounding errors that accumulate over time?
  26. structured bindings
Point p1{100, 200};
auto[a,b] = p1;
assert(a == 100 && b == 200);
  1. use cout.setf(ios::unitbuf) to disable cout buffering in debug mode
  2. use stronger types:
    • void something(int width, int height) -> void something(const Area& area)
  3. never return raw pointers!
  4. prefer stack over heap memory!
    • never use “new”
    • prefer std::array over std::vector
  5. avoid using std::bind and std::function!
  6. Error Handling with std::expected
  7. avoid usig initializer_lists for non trivial types
    • constructs an initializer_list object
      • calls the initializer_list constructor
      • overhead that is often unwanted

TODO: 23.11.2025

Video: Libraries - Writing code that others can use

cmake_minimum_required(VERSION 3.30)
project(MyLib LANGUAGES CXX)

add_library(mylib 
    "src/library.cpp"
)

set_target_properties(mylib
    PROPERTIES 
    CMAKE_CXX_STANDARD 23
    CMAKE_CXX_STANDARD_REQUIRED ON
    CMAKE_CXX_EXTENSIONS OFF
)

include(GNUInstallDirs)

target_include_directories(mylib
    PUBLIC
    "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>"
    "$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
)

install(TARGETS mylib 
    EXPORT DESTINATION ${CMAKE_INSTALL_LIBDIR}
    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
    INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)

install(FILES "src/library.hpp DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})

install(EXPORT mylibTargets
    FILE mylibTargets.cmake
    NAMESPACE mylib::
    DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/mylib"
)

include(CMakePackageConfigHelpers)

configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/Config.cmake.in
    "${CMAKE_CURRENT_BINARY_DIR}/mylibConfig.cmake"
    INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/mylib"
)

install(FILES
    "${CMAKE_CURRENT_BINARY_DIR}/mylibConfig.cmake"
    DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/mylib"
)
@PACKAGE_INIT@

include("${CMAKE_CURRENT_LIST_DIR}/mylibTargets.cmake")

chack_required_components(mylib)

include(CMakeFindDependencyMacro)
find_dependency(ZLIB REQUIRED)

TODO: 25.11.2025

Video: Understanding REST

TODO: 27.11.2025

Video: Building a simple Networking Library

TODO: 1.12.2025

Video: Postman-Clone Project

TODO: 2.12.2025

Video: Math Library Project

TODO: 3.12.2025

Video: Building a custom C2 Framework

TODO: 4.12.2025

Video: Structuring a Core / Game Engine Library Project

Utility Libraries

Building a logger library

#include <string>
#include <format>

int main(){
    std::string s{ std::format("Some {} cool", 5) };
}
#include <stack_trace>
#include <print>

void my_func() {
    std::println(std::stacktrace::current())
}

TODO: 5.12.2025

Video: Writing an AI-Library

TODO: 6.12.2025

Video: Writing a Crypto Trading Bot using our Core Library

TODO: 7.12.2025

CPack - Packaging C++ Software for Distribution

TODO: 8.12.2025

Build Web-Frontends in C++ using EMSCRIPTEN

ifdef __EMSCRIPTEN__
#include <emscripten.h>
endif
cmake_minimum_required(VERSION 3.30 FATAL ERROR)
project(testing c CXX)

if(EMSCRIPTEN)
    set(CMAKE_EXECUTABLE_SUFFIX ".html")
endif()

TODO: 9.12.2025

Utilizing Perf for performance insights

TODO: 10.12.2025

C++ - Performance Deep Dive

Optimizations:

Some things to consider checking for

Always test the result

TODO: 11.12.2025

Video Game AI-Programming

TODO: 12.12.2025

C++ Checklist - Before you Release

TODO: 13.12.2025

Code Review & Refactoring - Cube Engine

How to read the old crap?

In this series we have been heavily focused on learning modern C++23, but in production you still need to be able to read “C with Classes” and know yourself around. This is why we will cover “all the old crap” in this video

Bithacks

Code Review: “Cube2: Sauerbraten”

clang-tidy plugin development

TODO: 14.12.2025

End of Playlist & Further Learning

C++ is paradigm agnostic. To Master C++ you need to know and understand these, so you can always choose the right tool for the job:

Familiarize yourself with the C++ Core Guidelines: Core Guidelines

Stay up to date on isocpp.org