#include #include #include #include #include namespace flow { using VizFunctionPtr = auto (*)() -> std::string; struct graphviz_builder { template [[nodiscard]] static auto build(Graph const &input) { auto const nodes = flow::dsl::get_nodes(input); auto const edges = flow::dsl::get_edges(input); using nodes_t = std::set; nodes_t sources{}; nodes_t sinks{}; for_each( [&](Node const &) { sources.insert(Node::name_t::value); sinks.insert(Node::name_t::value); }, nodes); for_each( [&](Edge const &) { sinks.erase(Edge::source_t::name_t::value); sources.erase(Edge::dest_t::name_t::value); }, edges); std::string output{"digraph "}; output += std::string_view{Graph::name}; output += " {\n"; for (auto const &node : sources) { output += "start -> " + std::string{node} + '\n'; } for_each( [&](Edge const &) { output += std::string{Edge::source_t::name_t::value}; output += " -> "; output += std::string{Edge::dest_t::name_t::value}; output += '\n'; }, edges); for (auto const &node : sinks) { output += std::string{node} + " -> end\n"; } output += "}"; return output; } template class built_flow { static auto built() { auto const v = Initialized::value; return build(v); } static auto run() -> std::string { return built(); } public: // NOLINTNEXTLINE(google-explicit-constructor) constexpr explicit(false) operator VizFunctionPtr() const { return run; } auto operator()() const -> std::string { return run(); } constexpr static bool active = true; }; template [[nodiscard]] constexpr static auto render() -> built_flow { return {}; } }; } // namespace flow