#include #include template struct overloaded : Ts... { using Ts::operator()...; }; template overloaded(Ts...) -> overloaded; enum Color { R, B }; using E = std::monostate; template struct Node; template using Ptr = std::unique_ptr>; template using Tree = std::variant, Ptr>; template struct Node { static constexpr auto C = Col; Tree left; T value; Tree right; }; template Tree tree(A&& a, T& x, B&& b) { return Tree{Ptr{new Node{std::move(a), std::move(x), std::move(b)}}}; } template Tree balance(Tree s) { auto&& ll = [](Ptr& s, Ptr& t, auto&, Ptr& u, auto&, auto&, auto&) { auto& [a, x, b] = *s; auto& [s_, y, c] = *t; auto& [t_, z, d] = *u; return tree(tree(a, x, b), y, tree(c, z, d)); }; auto&& lr = [](auto&, Ptr& s, Ptr& t, Ptr& u, auto&, auto&, auto&) { auto& [a, x, t_] = *s; auto& [b, y, c] = *t; auto& [s_, z, d] = *u; return tree(tree(a, x, b), y, tree(c, z, d)); }; auto&& rl = [](auto&, auto&, auto&, Ptr& s, Ptr& t, Ptr& u, auto&) { auto& [a, x, u_] = *s; auto& [b, y, c] = *t; auto& [t_, z, d] = *u; return tree(tree(a, x, b), y, tree(c, z, d)); }; auto&& rr = [](auto&, auto&, auto&, Ptr& s, auto&, Ptr& t, Ptr& u) { auto& [a, x, t_] = *s; auto& [b, y, u_] = *t; auto& [c, z, d] = *u; return tree(tree(a, x, b), y, tree(c, z, d)); }; auto&& l = [](auto& s) -> Tree& { return *std::visit(overloaded{[&](E) { return &s; }, [](auto& t) { return &t->left; }}, s); }; auto&& r = [](auto& s) -> Tree& { return *std::visit(overloaded{[&](E) { return &s; }, [](auto& t) { return &t->right; }}, s); }; return std::visit([&](auto&... ss) -> Tree { if constexpr (1 < std::is_invocable_v + std::is_invocable_v + std::is_invocable_v + std::is_invocable_v) throw std::logic_error{""}; else return overloaded{ll, lr, rl, rr, [&](auto&... ss) { return std::move(s); }}(ss...); }, l(l(s)), l(s), r(l(s)), s, l(r(s)), r(s), r(r(s))); } template Tree ins(T& x, Tree& s) { return std::visit(overloaded{ [&](E) -> Tree { return tree(s, x, s); }, [&](auto& t) { auto& [a, y, b] = *t; static constexpr auto Col = std::remove_reference_t::C; return x < y ? balance(tree(ins(x, a), y, b)) : y < x ? balance(tree(a, y, ins(x, b))) : std::move(s); }, }, s); } template Tree insert(T x, Tree s) { return std::visit(overloaded{ [](E) -> Tree { throw std::logic_error{""}; }, [](auto&& t) { auto& [a, y, b] = *t; return tree(a, y, b); } }, ins(x, s)); } #include template void print(Tree const& s, int i = 0) { std::visit(overloaded{ [](E) {}, [&](auto& t) { auto& [a, y, b] = *t; print(a, i + 1); std::cout << std::string(i, ' ') << "RB"[t->C] << " " << y << "\n"; print(b, i + 1); } }, s); } int main(int argc, char* argv[]) { auto t = Tree{}; for (auto i = 1; i != argc; ++i) t = insert(std::string{argv[i]}, std::move(t)); print(t); }