有没有一种干净的方法可以将重载集转换为适合与 std::visit 一起使用的访问者?

Is there a clean way to turn an overload set into a visitor suitable for use with std::visit?

假设我有一个重载集,如下所示:

class C
{
  public: 

    static void f(const A &);
    static void f(const B &);
};

我想做类似的事情

std::variant<A, B> v;

// ...

std::visit(C::f, v);

但这不能编译。是否有某种方法可以获取重载集并将其视为访问者或将其转换为访问者?

实际上,在进一步尝试之后,我意识到我可以做到

std::visit([](const auto & t) { C::f(t); }, v);

所以我将把它留在这里作为其他有相同问题的人的潜在解决方案。

如果可以创建 class C 的实例,则可以在 class C 上重载成员 operator() 以调用适当的函数关于变体类型:

#include <iostream>
#include <variant>

struct A {};
struct B {};

class C
{
    public:    
    template <typename T>
    void operator()(const T& t) { C::f(t); }

    static void f(const A &) { std::cout << "A\n"; }
    static void f(const B &) { std::cout << "B\n"; }
};

int main()
{
    std::variant<A, B> v_a = A{};
    std::variant<A, B> v_b = B{};
    C c;
    std::visit(c, v_a); // "A"
    std::visit(c, v_b); // "B"
    return 0;
}

如果您已经在使用 Boost,Boost.HOF has a utility to wrap an overload set for you: BOOST_HOF_LIFT:

std::visit(BOOST_HOF_LIFT(C::f), v);

Demo