使用std :: variant进行命名的静态调度

时间:2019-01-04 09:46:06

标签: c++ c++17

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

问题是我希望能够使用接受两个参数的命名静态方法为profile = profile.decode('utf-8') 定义一个访问者类。如何填写std::variant进行派遣工作?

Applicator::apply()

4 个答案:

答案 0 :(得分:7)

另一种解决方案:

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

答案 1 :(得分:5)

使用现在非常普遍的overloaded类模板技巧(以及Maxim的技巧来根据其const的{​​{1}}的性质对lambda进行排序)来创建一个具有SFINAE功能的函子可以为您寻找的逻辑建模:

operator()

请注意,这是我在Wandbox上测试过的所有Clang版本的ICE,但我没有找到解决方法。完美的转发留给读者练习:)

答案 2 :(得分:3)

嗯,std::is_invocable_r看起来像是首选的工具。
不幸的是,您将必须获得正确的重载类型,这将完全无法达到目的。

相反,请退后一步,使用库基础知识TS v2 中的std::is_detected或等效版本以及模板:

template <class... Xs>
using can_Visitor_apply = decltype(Visitor::apply(std::declval<Xs>()...));

if constexpr(std::is_detected_convertible<State, can_Visitor_apply, State&, Event&>())
    return Visitor::apply(s, e);

优点是您有一个编译时常数,可以挂断任意决定。缺点是(还)没有一个函数,您只需简单地调用它就可以了。

答案 3 :(得分:3)

如果访问者始终可以申请,那么代码可以很简单

return std::visit([&](auto e) { return Visitor::apply(s, e); }, e);

但是,由于Visitor不能总是适用,因此我们需要使用SFINAE,这需要一组重载的函数模板。功能模板可以这样定义:

template<class EventType>
static auto applyHelper(State s, EventType e, int)
    -> decltype(Visitor::apply(s, e)) // only enabled if Visitor::apply(s, e) is a valid expression
{
    return Visitor::apply(s, e);
}

template<class EventType>
static State applyHelper(State s, EventType e, long) // long gives a lower precedence
                                                     // in overload resolution when argument is 0
{
    return s;
}

然后可以实现Applicator::apply

  static State apply(State s, Event e) {
      return std::visit([&](auto e) { return applyHelper(s, e, 0); }, e);
  }
相关问题