C++ Mastery is a hands-on learning repository, not a production standard-library replacement. I use small C and C++ experiments to make lifetime, allocation, generic programming and failure behavior concrete as I move deeper into platform engineering.
Learning by rebuilding
Using a container is different from implementing its lifetime rules. The lab takes familiar concepts apart: when storage becomes an object, what a move actually transfers, what happens during reallocation and what must remain true when construction throws.
Object lifetime and ownership
The Tracer experiment logs construction, copying, moving, assignment and destruction. Its nested-scope example is deliberately small enough to follow by hand.
Tracer a{1};
{
Tracer b{2};
}
std::cout << "leaving function\n";
The same source explores copy/move operations and forced std::vector reallocation. Lifetime experiment →
Vector as the centerpiece
- Allocate raw storage Allocator + capacity
- Construct appended value Before aliased source can move
- Relocate existing objects std::move_if_noexcept
- Destroy old objects End their lifetimes
- Deallocate old storage Commit the new allocation
Constructing the appended element first matters for v.push_back(v[0]): the argument refers into the vector’s current allocation. Relocating it too early can change or invalidate the very value being appended.
for (; relocated < size_; ++relocated) {
std::construct_at(
new_elements + relocated,
std::move_if_noexcept(
data_[relocated]
)
);
}
The implementation separates allocation, construction, destruction and deallocation rather than treating them as one operation. Vector implementation →
Exception safety
Make failure happen on purpose
ThrowOnCopy counts live objects and throws after a chosen number of copies. The tests check that partially constructed copies are cleaned up.
Preserve the destination
Copy assignment builds a temporary before swapping. If the copy fails, the original destination remains intact; the test inspects its values and live-object count.
Clean up partial growth
The growth path tracks relocated objects and whether the appended object exists, then destroys completed constructions and releases the new allocation on failure.
Keep guarantees precise
move_if_noexcept prefers copying when a throwing move could weaken rollback. A throwing move-only type or self-move has different guarantees; the lab avoids assuming a universal unchanged-state promise.
Failure, self-copy and self-move experiments →
Alignment and layout
struct alignas(64) CacheLineData {
int values[16]{};
};
Printing addresses, offsets and address modulus makes alignment observable. It is a way to reason about layout and locality; this case study makes no cache-speedup or benchmark claim.
Modern C++ concepts
Concepts
Express the operations a template requires and observe how constraints shape overload selection.
Source ↗Template deduction
Follow which types are deduced and which conversions happen after deduction.
Source ↗Value categories and forwarding
Trace lvalues, rvalues, references and forwarding through function boundaries.
Source ↗Fold expressions
Reduce a parameter pack while making evaluation and operation choice explicit.
Source ↗Type deduction
Compare auto, decltype and reference behavior through runnable examples.
Source ↗RAII
Give resource ownership a lifetime boundary through an IntBuffer implementation.
Source ↗C before C++
The C vvector lab makes the lower layer explicit: raw storage, element size, allocation and the bookkeeping a generic container needs. It is a useful comparison with the typed object-lifetime rules in C++.
| C lab | C++ lab |
|---|---|
| Explicit byte storage and element sizes | Typed allocator-backed storage |
| Manual resource protocol | Construction, destruction and RAII |
| Caller-visible generic storage rules | Templates, forwarding and exception paths |
Tooling
The workspace uses CMake with C17 / C++26 settings and explicit warning flags. AddressSanitizer and UndefinedBehaviorSanitizer are enabled for selected targets, including the C vector and RAII labs; sanitizer coverage is not claimed for every target.
Small executables make it easy to isolate a question, inspect output, force a failure and return to the implementation. Build configuration →
Direction of travel
This work supports a longer move into AOSP, AAOS platform internals and native boundaries. It does not stand in for production platform experience. The aim is to build the understanding needed to reason about ownership, memory and failure when Android application code reaches into lower layers.