11
11
#include < stdx/tuple_algorithms.hpp>
12
12
#include < stdx/type_traits.hpp>
13
13
14
+ #include < boost/mp11/set.hpp>
15
+
14
16
#include < algorithm>
15
17
#include < array>
16
18
#include < cstddef>
20
22
#include < utility>
21
23
22
24
namespace flow {
25
+ template <typename T> using name_for = typename T::name_t ;
26
+
23
27
[[nodiscard]] constexpr auto edge_size (auto const &nodes,
24
28
auto const &edges) -> std::size_t {
25
29
auto const edge_capacities = transform (
26
30
[&]<typename N>(N const &) {
27
31
return edges.fold_left (
28
32
std::size_t {}, []<typename E>(auto acc, E const &) {
29
- if constexpr (std::is_same_v<typename E::source_t , N> or
30
- std::is_same_v<typename E::dest_t , N>) {
33
+ if constexpr (std::is_same_v<name_for<typename E::source_t >,
34
+ name_for<N>> or
35
+ std::is_same_v<name_for<typename E::dest_t >,
36
+ name_for<N>>) {
31
37
return ++acc;
32
38
} else {
33
39
return acc;
@@ -43,8 +49,6 @@ namespace flow {
43
49
44
50
template <template <stdx::ct_string, std::size_t > typename Impl>
45
51
struct graph_builder {
46
- template <typename T> using name_for = typename T::name_t ;
47
-
48
52
template <typename Node, std::size_t N, std::size_t E>
49
53
[[nodiscard]] constexpr static auto make_graph (auto const &nodes,
50
54
auto const &edges) {
@@ -119,9 +123,38 @@ struct graph_builder {
119
123
std::span{std::cbegin (ordered_list), std::size (ordered_list)}};
120
124
}
121
125
126
+ constexpr static void check_for_missing_nodes (auto nodes,
127
+ auto mentioned_nodes) {
128
+ constexpr auto get_name = []<typename N>(N) ->
129
+ typename N::name_t { return {}; };
130
+ auto node_names = stdx::transform (get_name, nodes);
131
+ auto mentioned_node_names = stdx::transform (get_name, mentioned_nodes);
132
+
133
+ using node_names_t = decltype (stdx::to_sorted_set (node_names));
134
+ using mentioned_node_names_t =
135
+ decltype (stdx::to_sorted_set (mentioned_node_names));
136
+
137
+ if constexpr (not std::is_same_v<node_names_t ,
138
+ mentioned_node_names_t >) {
139
+ using missing_nodes_t =
140
+ boost::mp11::mp_set_difference<mentioned_node_names_t ,
141
+ node_names_t >;
142
+
143
+ static_assert (
144
+ stdx::always_false_v<missing_nodes_t >,
145
+ " A node is referenced in the graph but not explicitly added "
146
+ " with the unary plus operator. The beginning of this error "
147
+ " shows you which nodes are missing." );
148
+ }
149
+ }
150
+
122
151
template <typename Graph>
123
152
[[nodiscard]] constexpr static auto build (Graph const &input) {
124
153
auto nodes = flow::dsl::get_nodes (input);
154
+ auto mentioned_nodes = flow::dsl::get_all_mentioned_nodes (input);
155
+
156
+ check_for_missing_nodes (nodes, mentioned_nodes);
157
+
125
158
auto edges = flow::dsl::get_edges (input);
126
159
127
160
constexpr auto node_capacity = stdx::tuple_size_v<decltype (nodes)>;
@@ -183,6 +216,15 @@ class graph {
183
216
return stdx::to_unsorted_set (t);
184
217
}
185
218
219
+ friend constexpr auto tag_invoke (flow::dsl::get_all_mentioned_nodes_t ,
220
+ graph const &g) {
221
+ auto t = g.fragments .apply ([](auto const &...frags ) {
222
+ return stdx::tuple_cat (
223
+ flow::dsl::get_all_mentioned_nodes (frags)...);
224
+ });
225
+ return stdx::to_unsorted_set (t);
226
+ }
227
+
186
228
friend constexpr auto tag_invoke (flow::dsl::get_edges_t , graph const &g) {
187
229
auto t = g.fragments .apply ([](auto const &...frags ) {
188
230
return stdx::tuple_cat (flow::dsl::get_edges (frags)...);
0 commit comments