5

With the following code how do I write the custom template deduction correctly?

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);
}

I have looked at several examples, but I cannot find one which uses the return of the std::visit.

Jason Aller
  • 3,541
  • 28
  • 38
  • 38
schultz
  • 316
  • 2
  • 14

1 Answers1

7

Your visitor does not need to deduce and encode the return type R -- one will be inferred by std::visit itself: deduced from the callable or fixed to a specified template argument (see below). That being said, it could be simplified to:

template <typename... Ts> struct visitor : Ts... { using Ts::operator()...; };
template <typename... Ts> visitor(Ts...) -> visitor<Ts...>;

In each visitor must, however, return the same type. You could avoid any type mismatch by, e.g., explicitly specifying one for each lambda expression:

State newState = std::visit( visitor{
        [](Idle state, HeartBeat event) -> State { return Error{}; },
        //                                 ~~~~^
        [](auto state, auto event) -> State { return state; }
        //                            ~~~~^
    }, currentState, e);

DEMO


In , the return type can be specified as the first template argument of std::visit:

State newState = std::visit<State>( visitor{
        //                  ~~~~^
        [](Idle state, HeartBeat event) { return Error{}; },
        [](auto state, auto event) { return state; }
    }, currentState, e);
Piotr Skotnicki
  • 46,953
  • 7
  • 118
  • 160
  • Wow great, I was not that far off, The return type R in the template deduction was pure desperation on how to get this to work. The major issue was actually specifying the specific return type of the lambdas. As you can deduse by the name of the function case3 i had some iterations, and could not get this working.... You saved me alot of time, and gave me some new insights. Thank you. – schultz Nov 24 '18 at 23:11