[英]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等)。
您基本上有两个选择:
为accept()
提供通用的返回类型,例如std::any
或其前身boost::any
。 或者,如果您的返回类型的数量有限,则为std::variant
/ boost::variant
。 这样,成员函数不必是模板-但调用者必须知道如何处理它。
将键入的结果存储在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.