Visitor pattern. Is void* an acceptable return type for a completely abstract interface?

こ雲淡風輕ζ 提交于 2019-12-03 14:46:30

If I get this right, I might have something useful. Referring to your sample at https://gist.github.com/d11wtq/9575063, you cannot have

class ASTNode {
public:
   template <class T>
   virtual T accept(Visitor<T> *visitor);
};

because there are no template virtual functions. However, you may have a generic class

template <class D, class T>
struct host {
   virtual T accept(Visitor<T> * visitor);
   // I guess, { return visitor->visit(static_cast <D*>(this)); }
};

and a collection

template <class D, class... T>
struct hosts : host <D, T>... { };

so that, when the set of possible return types is limited, you can say e.g.

class ASTNode : public hosts <ASTNode, T1, T2, T3> {
public:
   // ...
};

Now you have three different Visitor contracts of return types T1,T2,T3.

Maybe this is helpful.

Using return type covariance to make accept() calls type-safe:

class Visitor;

class ASTNode
{
public:
    virtual ASTNode* accept(Visitor* visitor);
};

class CallNode;
class BinaryExpressionNode;

class Visitor
{
public:
    virtual CallNode* visit(CallNode* node) = 0;
    virtual BinaryExpressionNode* visit(BinaryExpressionNode* node) = 0;
};

Implementations:

class CallNode : public ASTNode
{
public:
    CallNode(BinaryExpressionNode* left, BinaryExpressionNode* right);

    // return type covariance
    CallNode* accept(Visitor* visitor) override
    {
        return visitor->visit(this);
    }

    BinaryExpressionNode* left();
    BinaryExpressionNode* right();
};

class BinaryExpressionNode : public ASTNode
{
public:
    BinaryExpressionNode* accept(Visitor* visitor) override
    {
        return visitor->visit(this);
    }
}

class OptimizingVisitor : public Visitor
{
public:
    CallNode* visit(CallNode* node) override
    {
        // return type covariance will make this operation type-safe:
        BinaryExpressionNode* left = node->left()->accept(this);
        auto right = node->right()->accept(this);
        return new CallNode(left, right);
    }

    BinaryExpressionNode* visit(BinaryExpressionNode* node) override
    {
        return new BinaryExpressionNode(node);
    }
};
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!