我需要填写一些模板魔术才能使以下代码片段起作用。

问题是我希望能够使用接受两个参数的命名静态方法为 std::variant 定义访问者类。如何填写 Applicator::apply() 使调度工作?

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

最佳答案

另一种解决方案:

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

关于c++ - 使用 std::variant 命名的静态调度,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/54036439/

10-16 08:14