Files
Renderive/Kernel/src/renderive/base/node/Multiway_Node.hpp
T
2026-08-04 18:14:38 +08:00

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;
};