使用 std::variant 的 StateMachine,获得正确的自定义模板推导
StateMachine with std::variant, getting the custom template deduction right
下面的代码如何正确编写自定义模板推导?
template<class R, class State, class... Ts> struct visitor : Ts... { using Ts::operator()...; };
template<class R, class State, class... Ts> visitor(State, Ts...)->visitor<class R, State,Ts...>;
using Event = std::variant<HeartBeat, ConfigurationRead>;
using State = std::variant<Idle, Starting, Running, Error>;
void case3()
{
Event e;
State currentState;
State newState = std::visit( visitor{
[](Idle&& state, HeartBeat event) {std::cout << "Currently stopped, heartbeat received.\n"; return Error{}; }
}, currentState, e);
}
我看过几个例子,但我找不到一个使用 std::visit 的 return 的例子。
您的访问者不需要推导和编码 return 类型 R
-- 一个将由 std::visit
本身推导:从可调用推导或固定到指定模板参数(见下文)。也就是说,它可以简化为:
template <typename... Ts> struct visitor : Ts... { using Ts::operator()...; };
template <typename... Ts> visitor(Ts...) -> visitor<Ts...>;
在 c++17 中,每个访问者必须 return 相同类型。您可以避免任何类型不匹配,例如,为每个 lambda 表达式明确指定一个:
State newState = std::visit( visitor{
[](Idle state, HeartBeat event) -> State { return Error{}; },
// ~~~~^
[](auto state, auto event) -> State { return state; }
// ~~~~^
}, currentState, e);
在c++20中,return类型可以指定为std::visit
的第一个模板参数:
State newState = std::visit<State>( visitor{
// ~~~~^
[](Idle state, HeartBeat event) { return Error{}; },
[](auto state, auto event) { return state; }
}, currentState, e);
下面的代码如何正确编写自定义模板推导?
template<class R, class State, class... Ts> struct visitor : Ts... { using Ts::operator()...; };
template<class R, class State, class... Ts> visitor(State, Ts...)->visitor<class R, State,Ts...>;
using Event = std::variant<HeartBeat, ConfigurationRead>;
using State = std::variant<Idle, Starting, Running, Error>;
void case3()
{
Event e;
State currentState;
State newState = std::visit( visitor{
[](Idle&& state, HeartBeat event) {std::cout << "Currently stopped, heartbeat received.\n"; return Error{}; }
}, currentState, e);
}
我看过几个例子,但我找不到一个使用 std::visit 的 return 的例子。
您的访问者不需要推导和编码 return 类型 R
-- 一个将由 std::visit
本身推导:从可调用推导或固定到指定模板参数(见下文)。也就是说,它可以简化为:
template <typename... Ts> struct visitor : Ts... { using Ts::operator()...; };
template <typename... Ts> visitor(Ts...) -> visitor<Ts...>;
在 c++17 中,每个访问者必须 return 相同类型。您可以避免任何类型不匹配,例如,为每个 lambda 表达式明确指定一个:
State newState = std::visit( visitor{
[](Idle state, HeartBeat event) -> State { return Error{}; },
// ~~~~^
[](auto state, auto event) -> State { return state; }
// ~~~~^
}, currentState, e);
在c++20中,return类型可以指定为std::visit
的第一个模板参数:
State newState = std::visit<State>( visitor{
// ~~~~^
[](Idle state, HeartBeat event) { return Error{}; },
[](auto state, auto event) { return state; }
}, currentState, e);