52 lines
1.7 KiB
C++
52 lines
1.7 KiB
C++
#pragma once
|
|
#include <algorithm>
|
|
#include <cstddef>
|
|
#include <memory_resource>
|
|
#include <stdexcept>
|
|
#include <vector>
|
|
template <class Owner, class Tag = void>
|
|
class Multiway_Node {
|
|
public:
|
|
explicit Multiway_Node(Owner* owner = nullptr, std::pmr::memory_resource& memory_resource = *std::pmr::get_default_resource()) noexcept
|
|
: owner(owner), children(&memory_resource) {}
|
|
Multiway_Node(const Multiway_Node&) = delete;
|
|
Multiway_Node& operator=(const Multiway_Node&) = delete;
|
|
Multiway_Node(Multiway_Node&&) = delete;
|
|
Multiway_Node& operator=(Multiway_Node&&) = delete;
|
|
~Multiway_Node() {
|
|
detach();
|
|
for (Multiway_Node* child : children) {
|
|
child->parent = nullptr;
|
|
}
|
|
}
|
|
void append_child(Multiway_Node& child) {
|
|
insert_child(children.size(), child);
|
|
}
|
|
void insert_child(std::size_t index, Multiway_Node& child) {
|
|
if (&child == this || child.is_ancestor_of(*this)) {
|
|
throw std::invalid_argument("multiway node cycle");
|
|
}
|
|
child.detach();
|
|
child.parent = this;
|
|
children.insert(children.begin() + static_cast<std::ptrdiff_t>(index), &child);
|
|
}
|
|
void detach() noexcept {
|
|
if (!parent) {
|
|
return;
|
|
}
|
|
std::erase(parent->children, this);
|
|
parent = nullptr;
|
|
}
|
|
bool is_ancestor_of(const Multiway_Node& node) const noexcept {
|
|
for (const Multiway_Node* current = node.parent; current; current = current->parent) {
|
|
if (current == this) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
Owner* owner{};
|
|
Multiway_Node* parent{};
|
|
std::pmr::vector<Multiway_Node*> children;
|
|
};
|