A stack keeps the most recent item on top, which is the same access pattern used by simple undo histories.

stack A `std::stack` exposes only the top item and follows last-in, first-out order.
undo Undo histories use the newest action first, so a stack is a natural model.

Stack Undo

latest
stack_undo.cpp
Replay: real traced execution (multi-file project)
#include <iostream>
#include <stack>
#include <string>

int main() {
    std::string latest = "rename";

    std::stack<std::string> undo;
    undo.push("open");
    undo.push(latest);

    std::string next = undo.top();
    undo.pop();
    int remaining = static_cast<int>(undo.size());

    std::cout << "next=" << next << std::endl;
    std::cout << "remaining=" << remaining << std::endl;
    return 0;
}
#include <iostream>
#include <stack>
#include <string>

int main() {
    std::string latest = "delete";

    std::stack<std::string> undo;
    undo.push("open");
    undo.push(latest);

    std::string next = undo.top();
    undo.pop();
    int remaining = static_cast<int>(undo.size());

    std::cout << "next=" << next << std::endl;
    std::cout << "remaining=" << remaining << std::endl;
    return 0;
}
#include <iostream>
#include <stack>
#include <string>

int main() {
    std::string latest = "format";

    std::stack<std::string> undo;
    undo.push("open");
    undo.push(latest);

    std::string next = undo.top();
    undo.pop();
    int remaining = static_cast<int>(undo.size());

    std::cout << "next=" << next << std::endl;
    std::cout << "remaining=" << remaining << std::endl;
    return 0;
}
  1. latest ← rename, undo ← (empty), next ← rename, remaining ← 1

    5int main() {6    std::string latest→ rename = "rename"; //@latest="delete", "format"78    std::stack<std::string> undo→ (empty);9    undo(empty).push("open");10    undo(empty).push(latestrename);1112    std::string next→ rename = undo(empty).top();13    undo(empty).pop();14    int remaining→ 1 = static_cast<int>(undo(empty).size());1516    std::cout << "next=" << nextrename << std::endl;17    std::cout << "remaining=" << remaining1 << std::endl;18    return 0;19}
    outputnext=rename
    remaining=1
  1. latest ← delete, undo ← (empty), next ← delete, remaining ← 1

    5int main() {6    std::string latest→ delete = "delete";78    std::stack<std::string> undo→ (empty);9    undo(empty).push("open");10    undo(empty).push(latestdelete);1112    std::string next→ delete = undo(empty).top();13    undo(empty).pop();14    int remaining→ 1 = static_cast<int>(undo(empty).size());1516    std::cout << "next=" << nextdelete << std::endl;17    std::cout << "remaining=" << remaining1 << std::endl;18    return 0;19}
    outputnext=delete
    remaining=1
  1. latest ← format, undo ← (empty), next ← format, remaining ← 1

    5int main() {6    std::string latest→ format = "format";78    std::stack<std::string> undo→ (empty);9    undo(empty).push("open");10    undo(empty).push(latestformat);1112    std::string next→ format = undo(empty).top();13    undo(empty).pop();14    int remaining→ 1 = static_cast<int>(undo(empty).size());1516    std::cout << "next=" << nextformat << std::endl;17    std::cout << "remaining=" << remaining1 << std::endl;18    return 0;19}
    outputnext=format
    remaining=1