繁体   English   中英

具有模板化返回值解决方案的虚拟模板功能

[英]Virtual template function with templated return value workaround

关于必须为虚拟的模板化函数的变通办法的问题在这里很常见,尽管我找不到能解决我问题的任何东西,这是该问题的一个简单变体: 需要虚拟模板成员变通办法

所提出的方法使用类型擦除导致非常干净和简单的解决方案。 但是,如果我需要从visit()方法返回一个值怎么办? OP在他的问题中已经考虑了这一方面,但是由于他从未使用过结果,因此在解决方案中被忽略了。

现在想象一下这段代码:

template <typename T>
class BaseVisitor {
  public:
    BaseVisitor();
    T visit(BaseVisited *visited);
    virtual ~BaseVisitor();
}


class BaseVisited {
  BaseVisited();
  template <typename T>
    virtual T accept(BaseVisitor<T> *visitor) { return visitor->visit(this); };
  virtual ~BaseVisited();
}

即使应用了类型擦除技巧,我们仍然需要对accept()进行模板化。 还有其他想法吗?

注意:我不能使用基类作为返回值,正如在SO上的一些答案中所建议的那样,因为T也可以代表任何基类型(int,string等)。

您基本上有两个选择:

  1. accept()提供通用的返回类型,例如std::any或其前身boost::any 或者,如果您的返回类型的数量有限,则为std::variant / boost::variant 这样,成员函数不必是模板-但调用者必须知道如何处理它。

  2. 将键入的结果存储在Visitor对象中。 您必须存储它而不是返回它,但是至少可以保留类型。 您可以使用“ 访问者模式”来处理。 我们可以有具有不同结果类型的不同访客; 他们只是在内部存储它们:

     // a void visitor struct ShapePrinter : IShapeVisitor { void visit(const Square&) override { std::cout << "Square"; } void visit(const Circle&) override { std::cout << "Circle"; } }; // a double visitor struct ShapePerimeterComputer : IShapeVisitor { void visit(const Square& square) override { perimeter = 4. * square.sideLength; } void visit(const Circle& circle) override { perimeter = 2. * M_PI * circle.radius; } double perimeter = 0.; }; 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM