#pragma once #include #include #include "error.h" namespace saw { /** * Container with a simplistic approach to a tree */ template class tree; /** * Branch object holding sub trees */ template class branch final { private: std::vector> children_; public: branch() = default; ~branch() = default; error_or reserve(std::size_t siz){ try{ children_.reserve(siz); }catch(const std::exception& e){ (void) e; return make_error(); } return void_t{}; } error_or add(T leaf) { std::size_t index = size(); try { children_.push_back(std::move(leaf)); }catch(const std::exception& e){ (void)e; return make_error(); } return index; } error_or add() { std::size_t index = size(); try { children_.push_back(branch{}); }catch(const std::exception& e){ (void)e; return make_error(); } return index; } std::size_t size() const { return children_.size(); } tree& at(std::size_t i){ return children_.at(i); } const tree& at(std::size_t i) const { return children_.at(i); } }; template class tree final { private: using type = std::variant,T>; type tov_; friend class branch; public: tree():tov_{branch{}}{} tree(branch nd):tov_{std::move(nd)}{} tree(T val):tov_{std::move(val)}{} template bool is() const { return std::holds_alternative(tov_); } bool is_branch() const { return std::holds_alternative(tov_); } bool is_value() const { return std::holds_alternative(tov_); } template NT& get() { return std::get(tov_); } template const NT& get() const { return std::get(tov_); } branch& get_branch(){ return std::get>(tov_); } const branch& get_branch() const { return std::get>(tov_); } T& get_value(){ return std::get(tov_); } const T& get_value() const { return std::get(tov_); } template error_or extract(){ if(!is()){ return make_error(); } NT nd = std::move(std::get(tov_)); tov_ = branch{}; return nd; } template error_or replace(type nd){ auto eon = extract(); if(eon.is_error()){ return eon; } tov_ = std::move(nd); return eon; } error_or> extract_branch() { return extract>(); } error_or> replace_branch(type nd){ return replace>(std::move(nd)); } error_or extract_value() { return extract(); } error_or replace_value(type nd){ return replace(std::move(nd)); } }; }