Skip to content

Commit 5a6365f

Browse files
committed
add runtime_conditional and flow unary operator+
1 parent 6367d04 commit 5a6365f

File tree

14 files changed

+268
-227
lines changed

14 files changed

+268
-227
lines changed

examples/flow_daily_routine/main.cpp

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -95,14 +95,14 @@ struct self_care_component_t {
9595
// Extend flow services
9696
constexpr static auto config = cib::config(
9797

98-
cib::extend<morning_routine_t>(self_care_component_t::WAKE_UP >>
99-
self_care_component_t::EXERCISE >>
100-
self_care_component_t::TAKE_BATH),
101-
102-
cib::extend<evening_routine_t>(self_care_component_t::EXERCISE >>
103-
self_care_component_t::TAKE_BATH >>
104-
self_care_component_t::RELAX >>
105-
self_care_component_t::GO_TO_BED));
98+
cib::extend<morning_routine_t>(+self_care_component_t::WAKE_UP >>
99+
+self_care_component_t::EXERCISE >>
100+
+self_care_component_t::TAKE_BATH),
101+
102+
cib::extend<evening_routine_t>(+self_care_component_t::EXERCISE >>
103+
+self_care_component_t::TAKE_BATH >>
104+
+self_care_component_t::RELAX >>
105+
+self_care_component_t::GO_TO_BED));
106106
};
107107

108108
struct food_component_t {
@@ -119,10 +119,10 @@ struct food_component_t {
119119
constexpr static auto config = cib::config(
120120

121121
cib::extend<morning_routine_t>(self_care_component_t::TAKE_BATH >>
122-
food_component_t::BREAKFAST),
122+
+food_component_t::BREAKFAST),
123123

124124
cib::extend<evening_routine_t>(self_care_component_t::RELAX >>
125-
food_component_t::DINNER >>
125+
+food_component_t::DINNER >>
126126
self_care_component_t::GO_TO_BED));
127127
};
128128

@@ -142,14 +142,14 @@ struct dress_up_component_t {
142142

143143
cib::extend<morning_routine_t>(
144144
self_care_component_t::WAKE_UP >>
145-
dress_up_component_t::GET_READY_FOR_EXERCISE >>
145+
+dress_up_component_t::GET_READY_FOR_EXERCISE >>
146146
self_care_component_t::EXERCISE >>
147147
self_care_component_t::TAKE_BATH >>
148-
dress_up_component_t::GET_READY_TO_WORK >>
148+
+dress_up_component_t::GET_READY_TO_WORK >>
149149
food_component_t::BREAKFAST),
150150

151151
cib::extend<evening_routine_t>(
152-
dress_up_component_t::GET_READY_FOR_EXERCISE >>
152+
+dress_up_component_t::GET_READY_FOR_EXERCISE >>
153153
self_care_component_t::EXERCISE));
154154
};
155155

@@ -167,10 +167,10 @@ struct commute_component_t {
167167
constexpr static auto config = cib::config(
168168

169169
cib::extend<morning_routine_t>(food_component_t::BREAKFAST >>
170-
commute_component_t::GO_TO_OFFICE),
170+
+commute_component_t::GO_TO_OFFICE),
171171

172172
cib::extend<evening_routine_t>(
173-
commute_component_t::RETURN_HOME >>
173+
+commute_component_t::RETURN_HOME >>
174174
dress_up_component_t::GET_READY_FOR_EXERCISE));
175175
};
176176

@@ -206,7 +206,7 @@ struct daily_routine_component_t {
206206

207207
// we need to extend the MainLoop as cib::top implements
208208
// MainLoop service
209-
cib::extend<cib::MainLoop>(DAILY_ROUTINES));
209+
cib::extend<cib::MainLoop>(+DAILY_ROUTINES));
210210
};
211211

212212
struct person_routine_proj {

include/cib/config.hpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <cib/detail/config_item.hpp>
88
#include <cib/detail/exports.hpp>
99
#include <cib/detail/extend.hpp>
10+
#include <cib/detail/runtime_conditional.hpp>
1011

1112
#include <stdx/compiler.hpp>
1213

@@ -22,6 +23,7 @@ namespace cib {
2223
* @see cib::extend
2324
* @see cib::exports
2425
* @see cib::conditional
26+
* @see cib::runtime_conditional
2527
*/
2628
template <typename... Configs>
2729
[[nodiscard]] CONSTEVAL auto config(Configs const &...configs) {
@@ -72,4 +74,11 @@ template <typename Predicate, typename... Configs>
7274
Configs const &...configs) {
7375
return detail::conditional<Predicate, Configs...>{configs...};
7476
}
77+
78+
template <typename Predicate, typename... Configs>
79+
requires std::is_default_constructible_v<Predicate>
80+
[[nodiscard]] CONSTEVAL auto runtime_conditional(Predicate const &,
81+
Configs const &...configs) {
82+
return detail::runtime_conditional<Predicate, Configs...>{configs...};
83+
}
7584
} // namespace cib
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#pragma once
2+
3+
#include <cib/detail/config_details.hpp>
4+
#include <cib/detail/config_item.hpp>
5+
#include <cib/detail/extend.hpp>
6+
7+
#include <stdx/compiler.hpp>
8+
#include <stdx/tuple.hpp>
9+
#include <stdx/tuple_algorithms.hpp>
10+
11+
namespace cib::detail {
12+
template <typename Pred, typename... Configs>
13+
requires std::is_default_constructible_v<Pred>
14+
struct runtime_conditional : config_item {
15+
detail::config<Configs...> body;
16+
17+
CONSTEVAL explicit runtime_conditional(Configs const &...configs)
18+
: body{configs...} {}
19+
20+
[[nodiscard]] constexpr auto extends_tuple() const {
21+
return stdx::transform(
22+
[]<typename E>(E e) {
23+
auto args_tuple = stdx::transform(
24+
[](auto arg) {
25+
return make_runtime_conditional(Pred{}, arg);
26+
},
27+
e.args_tuple);
28+
29+
return stdx::apply(
30+
[](auto... args) {
31+
return extend<typename E::service_type,
32+
decltype(args)...>{args...};
33+
},
34+
args_tuple);
35+
},
36+
body.extends_tuple());
37+
}
38+
39+
[[nodiscard]] constexpr auto exports_tuple() const {
40+
return body.exports_tuple();
41+
}
42+
};
43+
} // namespace cib::detail

include/flow/detail/walk.hpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,11 @@ constexpr inline class get_finals_t {
4747

4848
constexpr inline class get_nodes_t {
4949
template <node N> friend constexpr auto tag_invoke(get_nodes_t, N &&n) {
50-
return stdx::make_tuple(std::forward<N>(n));
50+
if constexpr (std::remove_cvref_t<N>::is_reference) {
51+
return stdx::tuple{};
52+
} else {
53+
return stdx::make_tuple(std::forward<N>(n));
54+
}
5155
}
5256

5357
public:

include/flow/graph_builder.hpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,18 @@
2020
#include <utility>
2121

2222
namespace flow {
23+
template <typename T> using name_for = typename T::name_t;
24+
2325
[[nodiscard]] constexpr auto edge_size(auto const &nodes,
2426
auto const &edges) -> std::size_t {
2527
auto const edge_capacities = transform(
2628
[&]<typename N>(N const &) {
2729
return edges.fold_left(
2830
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>) {
31+
if constexpr (std::is_same_v<name_for<typename E::source_t>,
32+
name_for<N>> or
33+
std::is_same_v<name_for<typename E::dest_t>,
34+
name_for<N>>) {
3135
return ++acc;
3236
} else {
3337
return acc;
@@ -43,8 +47,6 @@ namespace flow {
4347

4448
template <template <stdx::ct_string, std::size_t> typename Impl>
4549
struct graph_builder {
46-
template <typename T> using name_for = typename T::name_t;
47-
4850
template <typename Node, std::size_t N, std::size_t E>
4951
[[nodiscard]] constexpr static auto make_graph(auto const &nodes,
5052
auto const &edges) {
@@ -124,6 +126,8 @@ struct graph_builder {
124126
auto nodes = flow::dsl::get_nodes(input);
125127
auto edges = flow::dsl::get_edges(input);
126128

129+
// TODO: check that all the nodes referenced in `edges` are in `nodes`
130+
127131
constexpr auto node_capacity = stdx::tuple_size_v<decltype(nodes)>;
128132
constexpr auto edge_capacity = edge_size(nodes, edges);
129133

include/flow/step.hpp

Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,23 +21,43 @@ struct rt_node {
2121
rt_node const &) -> bool = default;
2222
};
2323

24-
template <stdx::ct_string Name> struct ct_node : rt_node {
24+
template <stdx::ct_string Type, stdx::ct_string Name, bool IsReference,
25+
typename F, typename... Ps>
26+
struct ct_node : rt_node {
2527
using is_node = void;
28+
using type_t =
29+
decltype(stdx::ct_string_to_type<Type, sc::string_constant>());
30+
2631
using name_t =
2732
decltype(stdx::ct_string_to_type<Name, sc::string_constant>());
28-
};
2933

30-
template <stdx::ct_string Name, stdx::ct_string Type>
31-
static void log_name_func() {
32-
CIB_TRACE("flow.{}({})",
33-
stdx::ct_string_to_type<Type, sc::string_constant>(),
34-
stdx::ct_string_to_type<Name, sc::string_constant>());
35-
}
34+
constexpr static auto is_reference = IsReference;
35+
36+
constexpr static auto predicate = [] { return (Ps{}() and ...); };
37+
38+
constexpr static auto run_func = [] {
39+
if (predicate()) {
40+
F{}();
41+
}
42+
};
43+
44+
constexpr static auto log_func = [] {
45+
if (predicate()) {
46+
CIB_TRACE("flow.{}({})", type_t{}, name_t{});
47+
}
48+
};
49+
50+
constexpr ct_node() : rt_node{run_func, log_func} {}
51+
52+
constexpr auto operator+() const -> ct_node<Type, Name, false, F, Ps...> {
53+
return {};
54+
}
55+
};
3656

3757
namespace detail {
38-
template <stdx::ct_string Name, stdx::ct_string Type, typename F>
58+
template <stdx::ct_string Type, stdx::ct_string Name, typename F>
3959
[[nodiscard]] constexpr auto make_node() {
40-
return ct_node<Name>{{.run = F{}, .log_name = log_name_func<Name, Type>}};
60+
return ct_node<Type, Name, true, F>{};
4161
}
4262

4363
constexpr auto empty_func = []() {};
@@ -46,7 +66,7 @@ constexpr auto empty_func = []() {};
4666
template <stdx::ct_string Name, typename F>
4767
requires(stdx::is_function_object_v<F> and std::is_empty_v<F>)
4868
[[nodiscard]] constexpr auto action(F const &) {
49-
return detail::make_node<Name, "action", F>();
69+
return detail::make_node<"action", Name, F>();
5070
}
5171

5272
template <stdx::ct_string Name> [[nodiscard]] constexpr auto action() {
@@ -58,7 +78,7 @@ template <stdx::ct_string Name> [[nodiscard]] constexpr auto step() {
5878
}
5979

6080
template <stdx::ct_string Name> [[nodiscard]] constexpr auto milestone() {
61-
return detail::make_node<Name, "milestone", decltype(detail::empty_func)>();
81+
return detail::make_node<"milestone", Name, decltype(detail::empty_func)>();
6282
}
6383

6484
inline namespace literals {
@@ -75,4 +95,12 @@ template <stdx::ct_string S>
7595
return milestone<S>();
7696
}
7797
} // namespace literals
98+
99+
template <typename P, stdx::ct_string Type, stdx::ct_string Name,
100+
bool IsReference, typename F, typename... Ps>
101+
constexpr auto
102+
make_runtime_conditional(P, ct_node<Type, Name, IsReference, F, Ps...>) {
103+
return ct_node<Type, Name, IsReference, F, P, Ps...>{};
104+
}
105+
78106
} // namespace flow

include/seq/step.hpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,17 @@ struct rt_step {
2323
operator==(rt_step const &, rt_step const &) -> bool = default;
2424
};
2525

26-
template <stdx::ct_string Name> struct ct_step : rt_step {
26+
template <stdx::ct_string Name, bool IsReference = true>
27+
struct ct_step : rt_step {
2728
using is_node = void;
2829
using name_t =
2930
decltype(stdx::ct_string_to_type<Name, sc::string_constant>());
31+
32+
constexpr static auto is_reference = IsReference;
33+
34+
constexpr auto operator+() const -> ct_step<Name, false> {
35+
return {forward_ptr, backward_ptr, log_name};
36+
}
3037
};
3138

3239
/**

test/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ add_unit_test(
121121
catalog_strings)
122122

123123
add_compile_fail_test(flow/fail/cyclic_flow.cpp LIBRARIES warnings cib)
124+
# add_compile_fail_test(flow/fail/only_reference_added.cpp LIBRARIES warnings cib) FIXME!
124125
add_compile_fail_test(msg/fail/callback_bad_field_name.cpp LIBRARIES warnings
125126
cib)
126127
add_compile_fail_test(msg/fail/field_location.cpp LIBRARIES warnings cib)

test/flow/fail/cyclic_flow.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ struct TestFlowAlpha : public flow::service<> {};
1313

1414
struct CyclicFlowConfig {
1515
constexpr static auto config = cib::config(
16-
cib::exports<TestFlowAlpha>, cib::extend<TestFlowAlpha>(a >> b >> a));
16+
cib::exports<TestFlowAlpha>, cib::extend<TestFlowAlpha>(+a >> +b >> a));
1717
};
1818
} // namespace
1919

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#include <cib/cib.hpp>
2+
#include <flow/flow.hpp>
3+
4+
namespace {
5+
using namespace flow::literals;
6+
7+
constexpr auto a = flow::milestone<"a">();
8+
9+
struct TestFlowAlpha : public flow::service<> {};
10+
11+
struct FlowConfig {
12+
constexpr static auto config =
13+
cib::config(cib::exports<TestFlowAlpha>, cib::extend<TestFlowAlpha>(a));
14+
};
15+
} // namespace
16+
17+
auto main() -> int {
18+
cib::nexus<FlowConfig> nexus{};
19+
nexus.service<TestFlowAlpha>();
20+
}

0 commit comments

Comments
 (0)