#pragma once #include #include #include "error.h" namespace saw { template class tree_or; template class tree final { private: std::vector> children_; public: tree() = default; ~tree() = default; 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(tree{}); }catch(const std::exception& e){ (void)e; return make_error(); } return index; } std::size_t size() const { return children_.size(); } tree_or& at(std::size_t i){ return children_.at(i); } const tree_or& at(std::size_t i) const { return children_.at(i); } }; template class tree_or final { private: using type = std::variant,T>; type tov_; friend class tree; public: tree_or():tov_{tree{}}{} tree_or(tree nd):tov_{std::move(nd)}{} tree_or(T val):tov_{std::move(val)}{} template bool is() const { return std::holds_alternative(tov_); } bool is_tree() 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_); } tree& get_tree(){ return std::get(tov_); } const tree& get_tree() 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_ = tree{}; 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_tree() { return extract>(); } error_or> replace_tree(type nd){ return replace>(std::move(nd)); } error_or extract_value() { return extract(); } error_or replace_value(type nd){ return replace(std::move(nd)); } }; }