At the end of part 9 we realized that our buffer still had one issue. Our copy constructor placement-news each element one at a time; if the third of five copies throws, the first two are already built, but because the constructor itself failed, the object’s destructor will never run, and those two elements leak. The same fragility lives in push_back and emplace_back: we increment count_ before we construct the element, so a throwing constructor leaves the buffer believing it holds an object that was never built, and our destructor will later walk into that slot and try to destroy it.

Personal Blog
Welcome to my blog. In here I will be posting writings about things I find interesting. Technology, programming, motorsport, storytelling, books, video game, etc. Maybe you will find something that you too find interesting or useful here. One of my goals for this section is to build a personal knowledge reference I can come back to when I get stuck on something.
Ring Buffer Series Part 9 — The Rule of Five - deep copies & noexcept
In part 6 we modified the buffer to work by storing bytes, this means that the compiler treats those bytes as raw data and not as the objects that data represents. This means that we also had to do the following:
RingBuffer(const RingBuffer&) = delete;
RingBuffer(RingBuffer&&) = delete;
RingBuffer& operator=(const RingBuffer&) = delete;
RingBuffer& operator=(RingBuffer&&) = delete;
Which effectively makes memberwise copy/move meaningless. Remember, we are using a raw byte buffer and placement new. Because of this we are managing object lifetimes manually. Usually a default compiler-generated copy would simply perform bitwise copy of the std::byte array and this creates a few problems. Bitwise copying does not call the actual copy constructors of the T objects stored in the buffer, so if T is a complex type such as std::string, copying its bits without calling the constructor would result in a shallow copy leading to a corrupted state or dangling pointers, if this isn’t bad enough, there is also wasted effort as the compiler would copy the entire buffer, including the empty slots that have not been constructed yet. Let us explore some concepts in more detail.
Ring Buffer Series Part 8 — Building in Place - emplace_back, variadic templates & perfect forwarding
We closed part 7 with some unfinished business, recall that push_back(T&&) still builds a temporary object and then moves it. Consider the output of our last example:
Pushing Temporary:
[Ctro] Created 1
[MOVE] Stealing data from 1
[Dtor] Destroyed 1
This works, but as a wise man once said; “we are still not happy”. What if we could get it to just [Ctro] Created 1. No temporary, no move?
The Goal: Construct From Arguments, Not From a Finished Object
Our push_back() takes a fully constructed object T. Unlike push_back(), emplace_back() takes a variadic number of arguments which are perfectly forwarded to the constructor of the element type T. This allows the object to be built directly in place within the container’s memory. Before we can move on to the implementation, there are some concepts that need to be explained.
Ring Buffer Series Part 7 — Move Semantics - Don't copy, steal
In part 6 we closed by pointing towards move semantics. In this post we will tackle the inefficiency of unnecessary copying, which happens when we create a temporary object, copy it into a container and then destroy the original. We acknowledged that this process is wasted work and in our RingBuffer it happens because our push_back implementation only supports copying, even when the source is a temporary object.
Consider the following:
Ring Buffer Series Part 6 — Storage and Lifetimes
We closed part 5 by promising to tackle move semantics, but there is foundational work that needs to be done before that can happen. Move semantics will come in the future, but in this post we need to make sure our storage is capable of supporting it and we will have to rebuild one of the components we made in part 2, so buckle up because this will be a long one.
Ring Buffer Series Part 5 — const_iterator
Previously we expanded our RingBuffer by implementing its own iterator class along with iterator traits. This allowed us to make it work with range-based for loops and most algorithms in the C++ Standard Library, but it still has a limitation.
void print_contents(const RingBuffer<int, 8>& buf)
{
for(auto x : buf)
{
std::cout << x << ' ';
}
}
The compiler will not allow it. Our begin() and end() are not const qualified, which means they can’t be called on a const object. In this episode we will fix this by introducing const_iterator, an iterator that promises not to modify the elements it visits.
Ring Buffer Series Part 4 — Iterators: Walking the Ring
In Part 3 we expanded on the original buffer and it now supports any type and any size. Our RingBuffer almost behaves like any of the STL types, such as std::vector and I say almost. Consider the following code:
int main()
{
RingBuffer<int, 10> my_buffer;
for (int i = 0; i < 10; ++i)
{
my_buffer.push_back(i);
}
for (auto x : my_buffer) // This line produces an error.
{
std::cout << x << ' ';
}
}
This code should work, but if we actually try to run it we will get a compiler error.
Ring Buffer Series Part 3 — Templates: One Buffer, Any Type, Any Size
In Part 2 we built a buffer that works, however it is stuck with unsigned int and size 8, but what if we wanted to use it with std::string or custom types like game events, or only store the last 4 frames? Do we write a buffer per class? We could, but that would be a nightmare, wouldn’t it?
Meet Templates
In C++, templates are a powerful mechanism for generating code. A template is a blueprint that the compiler uses to generate actual code. Think about it this way, a class is a blueprint for a thing (a type of thing), templates are blueprints for classes.
Ring Buffer Series Part 2 - Implementation
In Part 1 we covered the fundamental building blocks: classes, functions, constructors and how to organize code into header and implementation files. We created a simple Person class to illustrate these concepts and now it is time to apply what we learned to our main project: The RingBuffer.
Remember, our ring buffer needs to do a few key things: store elements, track where to add the next one, and know when it’s full. Let’s begin by creating a class.
Ring Buffer Series Part 1 - Classes and Functions - The Building Blocks
Hello! If you recall from the previous series, we built a program that handled text input, stored numbers into a vector and performed calculations. However there were some concepts in there that we used, but that I didn’t really explain. I am referring to iterators. In this new series I aim to go over what they are, how they work and how to use them, so get ready because it will be a bumpy ride and as usual, we will have to build our way there because fundamentals are always important.
Input Basics In C++ Part 3 - Multiple Inputs and Calculations
In Part 2 we covered some basic principles about standard input in C++, we talked about the input buffer stream, the iostate and some mechanisms that the C++ programming language provides us with to get input from users. We ended with a program that takes input from users and stores them, but that had the fatal flaw of only being able to store a single number, which really doesn’t make for a good calculator, does it?
So here are a few changes.
Input Basics In C++ Part 2 - Streams, Flags and Validation

In Part 1 of this series I covered some C++ fundamentals by building a small unit converter. While the program worked, it had a critical weakness: it assumed the “happy path,” where users never make mistakes. In the real world, things are messy, and as programmers, we have to anticipate how our applications might fail. We can’t predict everything, but we can certainly guard against the most common issues.
Input Basics In C++ Part 1 - Introduction
In your programming journey, have you ever reached a point where you feel overwhelmed with everything a language can do, leaving you unsure of what to learn first or which features are truly important? I find myself in that exact situation. With each new C++ standard, I feel like I’m falling behind. Here we are in 2025, and I’m still trying to master move semantics and how to best use smart pointers. Learning a language with a rich history like C++ can be grueling. I’ve noticed I often get mesmerized by what’s new, shiny, and exciting, causing me to neglect the fundamentals.
That’s what this post is about: practicing some of the fundamentals of the language and its standard library.
In this new series, I will explore the basics of the <iostream> library.
Replicating Cropout's Transition Animation
If you are an Unreal Engine developer, then you may be familiar with the Cropout sample project. This project has a lot to offer when it comes to the Engine’s capabilities and I have started a personal journey to reverse engineer it to see how I can enhance my own projects.
Cropout features a screen transition animation that I like and I also thought it would be a great starting point to learn from, so this post is about how I replicated the transition from scratch.
Storytelling For Beginners - Part 3
Welcome to the final part of the Storytelling for Beginners series.
Your Greatest Tool
Personal taste is the greatest tool you can have as an storyteller, the trick however is being able to justify why something you like matters to you. It is not about your ability anymore, but about the things that you like. The things that you are passionate about will direct your ability and inform your storytelling process.
Storytelling For Beginners - Part 2
Welcome to part two of the Storytelling for beginners series.
The Secret to Engagement
The secret to storytelling engagement is… wait for it, wait for it… wait for it… I bet you are thinking “Oh come on, just tell me already!” If you are, then my evil plan to illustrate the concept worked, the answer is tension.
Tension is the space between two opposing forces. It is when the audience doesn’t know the answer to a question in your story or the reasons why something is happening or what is about to happen. The secret of suspense lies in how good you are at keeping secrets. Hang on to a key fact for as long as possible, give hints about it as you, but don’t reveal everything at once or too soon.
Storytelling For Beginners - Part 1
Storytelling is one of the most underrated skills anyone can have. It lies at the center of our lives even if we don’t notice it. Storytelling is how we teach, learn, and evolve. Narrative helps us focus. It is everywhere.
- Do you want to impress girls? Tell them a good story.
- Do you want to be successful in a job interview? Connect with your interviewer by telling a good story instead of mindlessly spitting out facts.
- Do you want to teach programming so that your students learn and remember? Tell them programming related stories.
In this series of articles, I aim to share the basics of what I have learned about starting your journey as a storyteller.