C++ 工厂返回boost::visitor对象

C++ 工厂返回boost::visitor对象,c++,boost,c++98,C++,Boost,C++98,我希望创建一个访问者工厂,它返回以下任一类型的对象: class Visitor1: public boost::static_visitor<int> { public: int operator()(int& ) const { return 1; } int operator()(bool& ) const { return 1; } }; class Visitor2: p

我希望创建一个访问者工厂,它返回以下任一类型的对象:

class Visitor1: public boost::static_visitor<int>
{
public:
    int operator()(int& ) const 
    {
        return 1;
    }

    int operator()(bool& ) const 
    {
        return 1;
    }
};

class Visitor2: public boost::static_visitor<int>
{
public:
    int operator()(int& ) const 
    {
        return 2;
    }

    int operator()(bool& ) const 
    {
        return 2;
    }
};
类访问者1:public boost::static\u访问者
{
公众:
int运算符()(int&)常量
{
返回1;
}
int运算符()(bool&)const
{
返回1;
}
};
类访问者2:公共boost::static\u访问者
{
公众:
int运算符()(int&)常量
{
返回2;
}
int运算符()(bool&)const
{
返回2;
}
};
我假设我可以为工厂创建的对象返回boost::static_visitor*类型的指针,但这不会编译。我也不能引用该对象,如下所示:

Visitor1 v;
Type t;
boost::static_visitor<int>& vR = v;
boost::apply_visitor(vR, t);
visitor1v;
t型;
boost::static_visitor&vR=v;
boost::应用访问者(vR,t);
我得到的错误是:

see reference to function template instantiation 'int boost::apply_visitor<boost::static_visitor<R>,Type>(Visitor &,Visitable &)' being compiled
1>          with
1>          [
1>              R=int,
1>              Visitor=boost::static_visitor<int>,
1>              Visitable=Type
1>          ]
1>c:\boost_1_49_0\boost\variant\variant.hpp(858): error C2064: term does not evaluate to a function taking 1 arguments 
请参阅正在编译的函数模板实例化“int boost::apply_visitor(visitor&,Visitable&)”的参考
1> 与
1>          [
1> R=int,
1> Visitor=boost::static\u Visitor,
1> Visitable=类型
1>          ]
1> c:\boost\u 1\u 49\u 0\boost\variant\variant.hpp(858):错误C2064:术语不计算为带1个参数的函数

我应该如何实现我的工厂?

访问者使用重载,这意味着他们是一个静态组件。工厂总是(?)意味着运行时组件。首先,确定所有派生访问者是否共享同一组重载很重要。如果是,您可以使用此方案:

#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;
}
#包括
#包括
#包括
struct visitor\u base:public boost::static\u visitor
{
虚拟整数运算符()(整数)=0;
虚拟整数运算符()(双)=0;
虚拟整数运算符()(常量字符*)=0;
虚拟~visitor_base(){}
};
结构impl_1:访问者库{
虚拟int运算符()(int){return 1;}
虚拟int运算符()(双精度){return 1;}
虚拟整型运算符()(常量字符*){return 1;}
};
结构impl_2:访问者库{
虚拟int运算符()(int){return 2;}
虚拟整型运算符()(双){return 2;}
虚拟整型运算符()(常量字符*){return 2;}
};
std::唯一访客工厂(int i){
如果(i==1){
返回std::unique_ptr(新impl_1);
}否则{
返回std::unique_ptr(新impl_2);
}
}
int main()
{
自动视野=参观工厂(1);
变量v=3;

std::cout访问者使用重载,这意味着他们是一个静态组件。工厂总是(?)意味着一个运行时组件。首先,确定所有派生访问者是否共享同一组重载很重要。如果是,您可以使用此方案:

#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;
}
#包括
#包括
#包括
struct visitor\u base:public boost::static\u visitor
{
虚拟整数运算符()(整数)=0;
虚拟整数运算符()(双)=0;
虚拟整数运算符()(常量字符*)=0;
虚拟~visitor_base(){}
};
结构impl_1:访问者库{
虚拟int运算符()(int){return 1;}
虚拟int运算符()(双精度){return 1;}
虚拟整型运算符()(常量字符*){return 1;}
};
结构impl_2:访问者库{
虚拟int运算符()(int){return 2;}
虚拟整型运算符()(双){return 2;}
虚拟整型运算符()(常量字符*){return 2;}
};
std::唯一访客工厂(int i){
如果(i==1){
返回std::unique_ptr(新impl_1);
}否则{
返回std::unique_ptr(新impl_2);
}
}
int main()
{
自动视野=参观工厂(1);
变量v=3;

std::cout Thank!我还留下了一个可以用来解决此问题的接口。但是,我只应用于您提到的可能类型的子集。我计划使用模板捕获与特定访问者实现不相关的所有类型,但您不能混合使用虚拟和模板。我该如何解决这个问题d调用与特定访问者实现不相关的每种类型的断言。您的意思是我应该用引发异常的虚拟函数替换基类中的每个纯虚拟函数吗?@Baz,而您不能调用模板化的
运算符()
virtual,您可以使用visitor\u base::operator()通过
将其纳入派生访问者的范围
@pnr你介意编辑你的答案,用一个简单的例子来说明这一点吗?谢谢!@Baz我添加了第二个例子,展示了catch-all的情况。这里有很多取决于你的确切用例。所有派生的函子都覆盖相同的重载还是只有部分重叠等。它可能变得相当脆弱。谢谢!我还留下了一个接口c我将用于解决此问题。但是,我仅应用于您提到的可能类型的子集。我计划使用模板捕获与特定访问者实现不相关的所有类型,但您不能混合使用虚拟和模板。我如何解决此问题,或者需要为每个不相关的类型调用断言与特定访问者实现相关。您的意思是我应该用引发异常的虚拟函数替换基类中的每个纯虚拟函数吗?@Baz,而您不能调用模板化的
操作符()
virtual,您可以使用visitor\u base::operator()通过
将其纳入派生访问者的范围
@pnr您是否介意编辑您的答案,用一个简单的示例来演示这一点?谢谢!@Baz我添加了第二个示例,显示了“全面覆盖”的情况。这在很大程度上取决于您的具体使用情况。所有派生函子是否覆盖相同的重载或仅存在部分重叠等。它可能变得相当脆弱。