访问者使用重载,这意味着它们是静态组件。工厂总是(?)意味着运行时组件。首先,重要的是确定所有派生访问者是否共享同一组重载。如果是这样,您可以使用此方案:
#include <memory>
#include <boost/variant.hpp>
#include <boost/variant/static_visitor.hpp>
struct visitor_base : public boost::static_visitor<int>
{
  virtual int operator()(int) = 0;
  virtual int operator()(double) = 0;
  virtual int operator()(const char*) = 0;
  virtual ~visitor_base() {}
};
struct impl_1 : visitor_base {
  virtual int operator()(int) { return 1; }
  virtual int operator()(double) { return 1; }
  virtual int operator()(const char*) { return 1; }
};
struct impl_2 : visitor_base {
  virtual int operator()(int) { return 2; }
  virtual int operator()(double) { return 2; }
  virtual int operator()(const char*) { return 2; }
};
std::unique_ptr<visitor_base> visitor_factory(int i) {
  if(i == 1) {
    return std::unique_ptr<visitor_base>(new impl_1);
  } else {
    return std::unique_ptr<visitor_base>(new impl_2);
  }
}
int main()
{
  auto vis = visitor_factory(1);
  boost::variant<int, double, const char*> v = 3;
  std::cout << boost::apply_visitor(*vis, v) << std::endl;
  auto vis2 = visitor_factory(2);
  std::cout << boost::apply_visitor(*vis2, v) << std::endl;
  return 0;
}
如果您的派生访问者仅打算应用于变体中可能类型的子集,则您不能使用纯虚函数,并且需要一些报告失败的机制来处理基中的值(例如异常)。
当然,示例代码中使用的少数 C++11 功能很容易替换。
#include <memory>
#include <string>
#include <boost/variant.hpp>
#include <boost/variant/static_visitor.hpp>
struct visitor_base : public boost::static_visitor<int>
{
  // the catch all
  template <typename T>
  int operator()(const T& t) {
    return 0;
  }
  virtual int operator()(int) {}
  virtual int operator()(double) {}
  virtual int operator()(const char*) {}
  virtual ~visitor_base() {}
};
struct impl_1 : visitor_base {
  virtual int operator()(int) { return 1; }
  virtual int operator()(double) { return 1; }
  virtual int operator()(const char*) { return 1; }
};
struct impl_2 : visitor_base {
  virtual int operator()(int) { return 2; }
  virtual int operator()(double) { return 2; }
  virtual int operator()(const char*) { return 2; }
};
std::unique_ptr<visitor_base> visitor_factory(int i) {
  if(i == 1) {
    return std::unique_ptr<visitor_base>(new impl_1);
  } else {
    return std::unique_ptr<visitor_base>(new impl_2);
  }
}
int main()
{
  auto vis = visitor_factory(1);
  boost::variant<int, double, const char*> v = 3;
  std::cout << boost::apply_visitor(*vis, v) << std::endl;
  auto vis2 = visitor_factory(2);
  std::cout << boost::apply_visitor(*vis2, v) << std::endl;
  // a variant with more than impl_1 and impl_2 can catch
  boost::variant<int, double, const char*, std::string> vv = std::string{"asdf"};
  std::cout << boost::apply_visitor(*vis2, vv) << std::endl;
  // no use one that we handle
  vv = 3;
  std::cout << boost::apply_visitor(*vis2, vv) << std::endl;
  return 0;
}