#pragma once #include #include #include #include namespace flow::dsl { template struct seq { Lhs lhs; Rhs rhs; using is_subgraph = void; constexpr auto operator*() const { return seq{Lhs{}, Rhs{}}; } private: friend constexpr auto tag_invoke(get_initials_t, seq const &s) { return get_initials(s.lhs); } friend constexpr auto tag_invoke(get_finals_t, seq const &s) { return get_finals(s.rhs); } friend constexpr auto tag_invoke(get_nodes_t, seq const &s) { if constexpr (Identity == subgraph_identity::VALUE) { auto all_nodes = stdx::to_unsorted_set( stdx::tuple_cat(get_all_mentioned_nodes(s.lhs), get_all_mentioned_nodes(s.rhs))); return stdx::transform([](auto const &n) { return *n; }, all_nodes); } else { return stdx::tuple_cat(get_nodes(s.lhs), get_nodes(s.rhs)); } } friend constexpr auto tag_invoke(get_all_mentioned_nodes_t, seq const &s) { return stdx::tuple_cat(get_all_mentioned_nodes(s.lhs), get_all_mentioned_nodes(s.rhs)); } friend constexpr auto tag_invoke(get_edges_t, seq const &s) { auto is = get_initials(s.rhs); auto fs = get_finals(s.lhs); return stdx::tuple_cat( get_edges(s.lhs), get_edges(s.rhs), transform( [](P const &) { return edge, stdx::tuple_element_t<1, P>, Cond>{}; }, cartesian_product_copy(fs, is))); } }; template seq(Lhs, Rhs) -> seq; } // namespace flow::dsl template [[nodiscard]] constexpr auto operator>>(Lhs const &lhs, Rhs const &rhs) { return flow::dsl::seq{lhs, rhs}; } template constexpr auto make_runtime_conditional(Cond, flow::dsl::seq) { auto lhs = make_runtime_conditional(Cond{}, Lhs{}); auto rhs = make_runtime_conditional(Cond{}, Rhs{}); using lhs_t = decltype(lhs); using rhs_t = decltype(rhs); using cond_t = decltype(EdgeCond{} and Cond{}); return flow::dsl::seq{lhs, rhs}; }