Вашему посетителю не нужно выводить и кодировать тип возвращаемого значения 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);
DEMO
In c ++ 20 , тип возвращаемого значения может быть указан в качестве первого аргумента шаблона std::visit
:
State newState = std::visit<State>( visitor{
// ~~~~^
[](Idle state, HeartBeat event) { return Error{}; },
[](auto state, auto event) { return state; }
}, currentState, e);