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: - is fast - can do everything - can run everywhere - will be maintained and runable in the far future - becomes faster over time due to regular optimizatios

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

Video 1: 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 2: 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 3: 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 4: “Hello World!” using C++23 and CMake

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

Video 5: C++ Modules Basics using CMake

Video 6: Cross-Platform File Management

Video 7: Basic C++ Syntax

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

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

Video 9: Modularize / Encapsulation

Video 10: 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 11: 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 12: Working with Files

Video 13: Get to know the STL & <algorithm>

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

Video 14: Ranges

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

Video 15: Basic inheritance

Video 16: 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 16.1: Using CDash

Video 17: 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 17.1: Using CCmake

Video 18: Using third party libraries

Video 19: GitHub - Version Control and CI/CD

Video 20: Memory Management in Modern C++

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++

Modern C++

Video 21: Working with Databases

Video 22: Exploring 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]");
  }
};

Video 23: Proper Testing and Code analysis

Video 24: Basics of Asyncronouts Programming & Coroutines

Video 25: Libraries to try

Video 26: 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
};

Video 27: Filler - General Tips

Video XX: Learning Rust

Video 28: Filler - More General Tips

Video XX: Filler - Templates still useful!

Video 29: Filler - Even More General Tips

Video 31: Filler - More Tips yt again!

Video 32: Filler - Oh no! Even more tips!

Point p1{100, 200};
auto[a,b] = p1;
assert(a == 100 && b == 200);

Video 33: Filler - C++ Code Smells

Video 34: Event Loops

Video 35: Understanding REST

Video 36: 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())
}

Video 37: Parallel Algorithms: Faster Data Processing

Example:

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

Video 38: 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)

Video 39: Debugging effectively

Video 40: Error Handling with std::expected

Video 41: Software Design

Video 41.2: Dependency Injection

Video 42: 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 43: Compression, Serialization and Encryption - Building a Safe file system

Video 44: Writing Unit Tests with Catch2

Video 45: Plugin System & Dynamic Libraries

Video 46: Scripting - Lua vs Chai a comparison

Video 47: Gems of the STL

Video 48: More Compile Time Programming

if constexpr(is_something()) {

}```

## Video 49: Building a Web-Backend in modern C++
- CRUD app for something
- probably using Boost.Beast or POCO
- Crow looks very cool and simple. Probably easier to use than beast
- https://github.com/oatpp/oatpp - Oat++ (my favourite so far)
- https://github.com/drogonframework/drogon

## Video 50: Our own std::function
- how does function work in detail
- std::bind and std::invoke
- building our own std::function

Simple impl:
```cpp

Extra features: - no locks - no memory allocations - move-only

Video 51: Making our std::function constexpr

Video 52: Implementing small function optimization

Video 53: Run code on the GPU (using OpenCL)

Video 54: Concurrency deep dive - Exploring more Options

#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();
}
- coroutines are like functions that can be paused and resumed
- co_yield or co_await pause a coroutine
- co_return ends/exits a coroutine
- no locks needed (the coroutines decides itself when it suspends)
- coroutine frame holds the information about the current state of the coroutine
    - very likely stored on the heap
- could replace callbacks

Video 55: Thead safe logger singleton

Video 56: Networking deep dive

Video 57: Build a web-game using emscripten

- is a compiler for c and c++ to WebAssembly
- emcc main.cpp -o hello_world.html
```cpp
ifdef __EMSCRIPTEN__
#include <emscripten.h>
endif
```
- cmake adjustments
```cmake
cmake_minimum_required(VERSION 3.30 FATAL ERROR)
project(testing c CXX)

if(EMSCRIPTEN)
    set(CMAKE_EXECUTABLE_SUFFIX ".html")
endif()
```
- use `emcmake` instead of `cmake` to build

Video 58: Android NDK

Video 59: Performance Deep dive - building a profiler

Video 60: Optimize all the things! Exploring performance hacks

Optimizations:

Some things to consider checking for

Video 61: Branchless Programming

Video 62: Clean Code

Video 63: Video Game AI Masterclass

Video 64: Cross-Platform Applications and Cross-Compilation

Video 65: Checklist before you Release

Video 66: Versioning - Semver

Video 67: CPack - Package your Program for distribution

Video 68: 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

Video 69: Bithacks

Video 70: Code Review: “Cube2: Sauerbraten”

Video 71: clang-tidy plugin development

- clang-query
- AST matchers
- fixit hints
- Transformer/Rewrite Rules

Video 72: Understand WinAPI Code

Video 73: SOLID - Design Principles

Video 74: Design Patterns

Video 75: CRTP - Curiously Recurring Template Pattern

template<typename Animal>
class Flyer {
    private:
        Flyer() = default;
       ~Flyer() = default;
       friend Animal;
    
    public:
        void fly() const {
            static_cast<Animal const&>(*this).fly();
        }
};

class Animal : public Flyer<Animal> {
    public:
    //...
    void fly() const {
        std::cout << "this animal custom flying\n";
    }
};

Video XX: More Template Magic

#include <type_traits>
template<typename T1, typename T2, typename RT = std::decay_t<decltype(true ? T1() : T2())>>
RT max (T1 a, T2 b) {
    return b < a ? a : b;
}```

- common_type decays to not become a reference type:
```cpp
#include <type_traits>
template<typename T1, typename T2,
typename RT = std::common_type_t<T1,T2>>
RT max (T1 a, T2 b) {
    return b < a ? a : b;
}
template<typename T>
class C {
    static_assert(std::is_default_constructible<T>::value,
    "Class C requires default-constructible elements");
    //...
};

Video 76: Event Driven Software Architecture

Video 77: Review & Road Ahead

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: - imperative - functional - concurrent - performance based - data oriented - test driven - …

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

Stay up to date on isocpp.org