Named, static dispatching with std::variant

  • A+
Category:Languages

I need to fill in some template magic to make the following code snippet to work.

The problem is that I want to be able to define a visitor class for std::variant with named static methods accepting two arguments. How can I fill in Applicator::apply() to make the dispatching work?

struct EventA {};  struct EventB {};  struct EventC {};  using Event = std::variant<EventA, EventB, EventC>;  struct Visitor {   enum class LastEvent { None, A, B, C };    struct State {     LastEvent last_event = LastEvent::None;   };    static State apply(State s, EventA e) { return State{LastEvent::A}; }    static State apply(State s, EventB e) { return State{LastEvent::B}; } };  template <typename Visitor> struct Applicator {    static State apply(State s, Event e) {      /*** Start of pseudo code ***/     if (Visitor can apply) {       return Visitor::apply(s, e);     }     /*** End of pseudo code ***/      // Else, don't update state state     return s;   } };  int main() {   // Handled by visitor   State s1 = Applicator<Visitor>::apply(State{}, EventA{});   assert(s1.last_event == Visitor::LastEvent::A);    // Handled by visitor   State s2 = Applicator<Visitor>::apply(State{}, EventB{});   assert(s2.last_event == Visitor::LastEvent::B);    // NOT handled by visitor   State s3 = Applicator<Visitor>::apply(State{}, EventC{});   assert(s3.last_event == Visitor::LastEvent::None); } 

 


Another solution:

using State = Visitor::State;  template<class Visitor> struct VisitorProxy {     State s;      template<class E>     auto operator()(E const& e) -> decltype(Visitor::apply(s, e)) {         return Visitor::apply(s, e);     }      template<class E>     State operator()(E const&) const {         return s;     } };  template <typename Visitor> struct Applicator {     static State apply(State s, Event e) {         VisitorProxy<Visitor> p{s};         return std::visit(p, e);     } }; 

Comment

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: