StateMachine с std:: вариантом, получая право вычета пользовательского шаблона
С помощью следующего кода, как правильно написать вывод шаблона?
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.
1 ответ
Решение
Вашему посетителю не нужно выводить и кодировать тип возврата R
- один будет выведен std::visit
себя: выводится из вызываемого или фиксируется в указанном аргументе шаблона (см. ниже). При этом, это может быть упрощено до:
template <typename... Ts> struct visitor : Ts... { using Ts::operator()...; };
template <typename... Ts> visitor(Ts...) -> visitor<Ts...>;
Однако в C++17 каждый посетитель должен возвращать один и тот же тип. Вы можете избежать любого несоответствия типов, например, явно указав его для каждого лямбда-выражения:
State newState = std::visit( visitor{
[](Idle state, HeartBeat event) -> State { return Error{}; },
// ~~~~^
[](auto state, auto event) -> State { return state; }
// ~~~~^
}, currentState, e);
В C++20 возвращаемый тип может быть указан в качестве первого аргумента шаблона std::visit
:
State newState = std::visit<State>( visitor{
// ~~~~^
[](Idle state, HeartBeat event) { return Error{}; },
[](auto state, auto event) { return state; }
}, currentState, e);