12.09 Generic Bounded LIFO Structures with Zero Runtime Heap Allocation
Executive Summary: Implementing a generic templated array stack. We explore type-safe compile-time instantiations, bounded memory guarantees, and why templated bounded arrays represent the gold standard container in safety-critical embedded systems.
💻 1. Annotated Source Code
#ifndef STACK_H #define STACK_H template <typename T> class Stack { public: virtual void push(const T& newEntry) = 0; virtual T pop() = 0; virtual T peek() const = 0; virtual bool isEmpty() const = 0; virtual void makeEmpty() = 0; virtual ~Stack() {} }; #endif
#ifndef ARRAY_STACK_H #define ARRAY_STACK_H #include "Stack.h" #include <iostream> using namespace std; template <typename T> class ArrayStack : public Stack<T> { public: ArrayStack(int s = 16) : MAX_SIZE(s) { top = -1; mArray = new T[MAX_SIZE]; }//end ctor ~ArrayStack() override { delete[] mArray; } void push(const T& newEntry) override { if (top < MAX_SIZE - 1) { top++; mArray[top] = newEntry; } else { cout << "Error: Stack is full! Cannot push." << endl; } }//end push T pop() override { if (!isEmpty()) { return mArray[top--]; } else { cout<<"You can't pop from an empty stack!"<<endl; return T(); } }//end pop T peek() const override { if (!isEmpty()) { return mArray[top]; } else { cout << "The stack is empty." << endl; return T(); } }//end peek bool isEmpty() const override { return top == -1; }//end isEmpty void makeEmpty() override { top = -1; } private: T* mArray; const int MAX_SIZE; int top; }; #endif
#include <iostream> #include <string> #include "ArrayStack.h" using namespace std; int main() { ArrayStack<string> words; words.push("apple"); words.push("banana"); words.push("cherry"); while (!words.isEmpty()) { cout << words.pop() << endl; } cout << endl << endl; cout << "Now let's try integers!" << endl; ArrayStack<int> nums; nums.push(10); nums.push(20); nums.push(30); while (!nums.isEmpty()) { cout << nums.pop() << endl; } cout << endl << endl; cout << "Testing ArrayStack with doubles..." << endl; ArrayStack<double> decimals; decimals.push(3.14); decimals.push(2.718); decimals.push(1.618); cout << "Top of decimal stack: " << decimals.peek() << endl; while (!decimals.isEmpty()) { cout << decimals.pop() << endl; } return 0; }
📐 2. Architecture & UML Class Model
<<interface>>
StackInterface<T>
Abstract Stack Contract
Attributes / Data Members
(none / stateless)
Operations / Methods
+push(newEntry: const T&) : bool[pure virtual =0]
+pop() : bool[pure virtual =0]
+peek() : T const[pure virtual =0]
+isEmpty() : bool const[pure virtual =0]
+~StackInterface()[virtual]
<<template class>>
TemplatedArrayStack<T>
Concrete Array Implementation
Attributes / Data Members
-items[CAPACITY] : T
-top : int32_t = -1
Operations / Methods
+TemplatedArrayStack()
+push(newEntry: const T&) : bool[override]
+pop() : bool[override]
+peek() : T const[override]
+isEmpty() : bool const[override]
🔗 Architectural Relationships & Hierarchy
TemplatedArrayStack<T>
- - ▷
implements interface
- - ▷
StackInterface<T>
📚 3. Core C++ Concepts Deep-Dive
1. Generic Template Containers
Combining templates with static arrays provides type safety for arbitrary data payloads while avoiding void* casts.
⚡ 4. Embedded Systems & Hardware Reality
1. Safety-Critical Compliance (AUTOSAR / MISRA)
Templated bounded array stacks allocate storage at compile time, guaranteeing zero dynamic memory operations after system initialization.
💡 5. Production-Ready Embedded Refactoring
💡 Production-Ready Refactor
#include <array> #include <optional> template <typename T, size_t MaxCapacity> class EmbeddedStack { public: bool push(const T& item) { if (top_ >= MaxCapacity) return false; data_[top_++] = item; return true; } std::optional<T> pop() { if (top_ == 0) return std::nullopt; return data_[--top_]; } private: std::array<T, MaxCapacity> data_; size_t top_ = 0; };
📝 Knowledge Verification Quiz
Test your understanding of the C++ concepts and embedded microcontroller trade-offs covered in this guide. Click any option for instant feedback.
Q1. Why is a templated bounded array stack considered the gold standard in AUTOSAR C++ embedded software?
Detailed Explanation:
It provides full generic type safety while bounding memory consumption strictly at compile time.