标签: visitor-pattern

调用boost :: variant中类型的通用方法

如果我boost::variant支持的所有类型都使用相同的方法,那么有没有办法一般地调用它(即不为每个方法单独调用它static_visitor)?

我正试图让这样的东西起作用:

class A
{
    void boo() {}
};

class B
{
    void boo() {}
};

class C
{
    void boo() {}
};

typedef boost::variant<A, B, C> X;

void foo(X& d)
{
    x.boo();
}
Run Code Online (Sandbox Code Playgroud)

但它无法编译说'boo' : is not a member of 'boost::variant<T0_,T1,T2>'.

目前,我有一些类都继承自接口,因此可以多态地使用它们的单个共享方法.我还希望能够通过访问者使用这些类,因为所有其他方法对于每个具体类都是唯一的.我希望boost::variant可能是在这里实现我自己的访问者机制的更好的替代方案.是吗?

c++ generic-programming visitor-pattern boost-variant

6
推荐指数
1
解决办法
1085
查看次数

如何在Swift中使用访问者模式减少样板?

我正在Swift 2.2中为工作项目实现访问者模式.

因此,我不需要简化我的源代码并节省一些时间,我将使用Oktawian Chojnacki在swift中的访客模式示例.

protocol PlanetVisitor {
    func visit(planet: PlanetAlderaan)
    func visit(planet: PlanetCoruscant)
    func visit(planet: PlanetTatooine)
}

protocol Planet {
    func accept(visitor: PlanetVisitor)
}

class PlanetAlderaan: Planet {
    func accept(visitor: PlanetVisitor) { visitor.visit(self) }
}
class PlanetCoruscant: Planet {
    func accept(visitor: PlanetVisitor) { visitor.visit(self) }
}
class PlanetTatooine: Planet {
    func accept(visitor: PlanetVisitor) { visitor.visit(self) }
}

class NameVisitor: PlanetVisitor {
    var name = ""

    func visit(planet: PlanetAlderaan)  { name = "Alderaan" }
    func visit(planet: PlanetCoruscant) { name …
Run Code Online (Sandbox Code Playgroud)

design-patterns visitor-pattern swift swift2

6
推荐指数
1
解决办法
597
查看次数

寻求更好地理解 std::visit

来自https://en.cppreference.com/w/cpp/utility/variant/visit

  1. 的返回值是多少visit?我不明白“访问者的选定调用”?

示例代码

// Don't understand what this means, can explain? It's a templated func with trailing return type but no body?
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;

// Why would the visitor function use && instead of &?
std::visit([](auto&& arg){std::cout << arg;}, v);
Run Code Online (Sandbox Code Playgroud)

c++ stl visitor-pattern

6
推荐指数
2
解决办法
6120
查看次数

C#中的用户可扩展访问者模式

是否可以在 C# 中创建用户可扩展的访问者模式?(最好是 .net 3.5)

我在库中有一组类,我希望使用访问者模式向其中添加功能。问题是库的用户也可以创建自己的类。这意味着您需要创建一个特殊的访问者来接受新的类类型,但我们的 Accept 方法被设置为接收基本类型。如何让派生类在派生访问者中调用正确的方法。

或者是否有另一种方式来做“如果是这种类型,就这样做”?

一些示例代码:

/* In library */
namespace VisitorPattern.System
{
   interface IThing
   {
      void Accept(SystemVisitor visitor);
      void ThingMethodA(...);
      void ThingMethodB(...);
   }

   class SystemThingA : IThing
   {
      public void Accept(SystemVisitor visitor) { visitor.Visit(this); }
      ...ThingMethods...
   }
   class SystemThingB : IThing
   {
      public void Accept(SystemVisitor visitor) { visitor.Visit(this); }
      ...ThingMethods...
   }
   class SystemThingC : IThing
   {
      public void Accept(SystemVisitor visitor) { visitor.Visit(this); }
      ...ThingMethods...
   }

   class SystemVisitor
   {
      public SystemVisitor(object specialSystemServices) { }
      public virtual …
Run Code Online (Sandbox Code Playgroud)

c# visitor-pattern

5
推荐指数
1
解决办法
2005
查看次数

OCaml访客模式

我在OCaml中实现了一个简单的类C语言,并且像往常一样,AST是我的中间代码表示.由于我将在树上进行一些遍历,我想实现访问者模式以减轻痛苦.我的AST目前遵循该语言的语义:

type expr = Plus of string*expr*expr | Int of int | ...
type command = While of boolexpr*block | Assign of ...
type block = Commands of command list
...
Run Code Online (Sandbox Code Playgroud)

现在的问题是树中的节点是不同类型的.理想情况下,我会将一个处理节点的函数传递给访问过程; 该过程将打开节点的类型并相应地进行工作.现在,我必须为每个节点类型传递一个函数,这似乎不是最佳解决方案.

在我看来,我可以(1)真正采用这种方法或(2)上面只有一种类型.通常的方法是什么?也许用OO?

ocaml functional-programming abstract-syntax-tree visitor-pattern

5
推荐指数
3
解决办法
1454
查看次数

访问者模式可以接受额外的参数吗

在实现访问者模式时,向 Accept 和 Visit 方法添加额外的参数是不是一个坏主意?我从未见过任何这样做的例子,但也没有提到这是一个坏主意。

我想在我的域模型中使用此模式,但是需要附加参数以及实体本身。

例如——

public interface ISomethingVisitor
{
    void Visit(Foo foo, int p1, int p2);
}

public interface ISomethingVisitable
{
    void Accept(ISomethingVisitor visitor, int p1, int p2);
}
Run Code Online (Sandbox Code Playgroud)

c# design-patterns domain-driven-design visitor-pattern

5
推荐指数
1
解决办法
1856
查看次数

子类节点上的访问者的 C++ 访问者模式失去了“是”关系

首先,抱歉,如果这是重复的。但我没有看到任何类似的东西。

我熟悉访问者模式,并且正在尝试为图表上的访问者添加更多的灵活性。如果我有节点类 A、B、C、SubB(继承 B),我希望能够有一个接受 B 节点的访问者,并且将自动接受 SubB 节点而不知道它们(定义accept())。

明显的好处是我可以整天进行子类化,并且访问者不需要关心为这些类型定义访问。

我有代码和结果要在下面演示。如您所见,以下是它将访问的节点。

new Node(),
new ANode(),
new BNode(),
new CNode(),
new BNode(),
new SubBNode()
Run Code Online (Sandbox Code Playgroud)

基本上 CountVisitor 正确地报告它发现了 2 个 B,我明白为什么。CountVisitor.visit(SubB&) 不会被覆盖,而是会重定向到 Visitor.visit(SubB&),从而跳过计数。然而,我想要它报告 3 ( 2 Bs + 1 SubB ) 的功能,因为 SubB “是一个” B。我已经考虑过这一点,但我只是不知道如何让类型系统做到这一点。我应该如何重新安排事物以实现该功能?如果保持“是”关系,我也愿意接受替代模式,但我确实认为如果这个障碍得到解决,访问者将是完美的。

#include <iostream>
#include <string>
#include <vector>

using namespace std;

class Visitor;

class Node
{
  public:
  vector<Node*> children;
  virtual void accept(Visitor&);
};

class ANode : public Node
{
  public:
  virtual void accept(Visitor&);

};
class BNode : public Node
{ …
Run Code Online (Sandbox Code Playgroud)

c++ inheritance design-patterns visitor-pattern

5
推荐指数
1
解决办法
525
查看次数

解释 Python 3.6 中的 AST:isinstance、猴子修补、visit_NodeType 与宏?

假设我想编写一个小型解释器,可以使用二元运算 Plus、一元运算Negate和整数常量来计算表达式。

我目前只对 AST 的解释感兴趣,因此为了简单起见,让我们跳过标记化和解析。

在 Haskell 中,有一种或多或少规范的方法来做到这一点:

data Ast = Plus Ast Ast | Negate Ast | IntConst Int

ev :: Ast -> Int
ev (Plus a b) = (ev a) + (ev b)
ev (Negate x) = - (ev x)
ev (IntConst i) = i

main = print $ show $ ev $ (Plus (IntConst 50) (Negate $ IntConst 8))
Run Code Online (Sandbox Code Playgroud)

现在,Python 3.6 似乎没有代数数据类型。我的问题是似乎有很多可能的解决方法。最明显的一个是使用isinstance

class Plus:
  def __init__(self, first, second):
    self.first = first
    self.second …
Run Code Online (Sandbox Code Playgroud)

python monkeypatching visitor-pattern algebraic-data-types python-3.x

5
推荐指数
1
解决办法
206
查看次数

如何使用 JavaParser 在同一行添加新语句

我知道JavaParser在 AST 上运行,但我很好奇是否可以在与另一条语句相同的行上添加新语句。让我举一个例子来说明我想要实现的目标。

输入示例X.java(不要介意“逻辑”):

public class X {
    public static void main(String[] args) {
        int a = 1;
        while(a < 100) {
            a *= 2;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我想要实现的是在System.out.println("End of loop reached");每个循环体的末尾添加语句 - 但是,如果可能的话,我想在循环体中的最后一个语句旁边添加这个新语句。因此,结果应该如下所示:

public class X {
    public static void main(String[] args) {
        int a = 1;
        while(a < 100) {
            a *= 2; System.out.println("End of loop reached");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

目前我使用以下访问者(用 Kotlin 编写),只是为了了解 JavaParser。然而,这会导致为打印语句添加新行。关于如何指示 JavaParser 在同一行添加新节点有什么想法吗?

class WhileVisitor : VoidVisitorAdapter<Void>() …
Run Code Online (Sandbox Code Playgroud)

java abstract-syntax-tree visitor-pattern javaparser code-transformation

5
推荐指数
0
解决办法
544
查看次数

具有可变返回类型的 C++ 访问者模式

我有以下设置:

class IVisitor{
public:
    virtual SomeType visit(IVisitable& visitable) = 0;
};

class IVisitable{
public:
    virtual SomeType accept(IVisitor& visitor) = 0;
};

class ConcreteVisitor : public IVisitor{
public:
    SomeType visit(IVisitable& visitable) override {
        return calculateSomeStuff();
    }
};

class ConcertVisitable : public IVisitable{
public:
    SomeType accept(IVisitor& visitor) override {
        return visitor.visit(*this);
    }
};
Run Code Online (Sandbox Code Playgroud)

但我希望不同的访问者返回不同的类型。为此,IVisitable::accept()还应该返回不同的类型。

这将导致以下(不正确)代码:

template <typename R>
class IVisitor{
public:
    virtual R visit(IVisitable& visitable) = 0;
};

class IVisitable{
public:
    template <typename R>
    virtual R accept(IVisitor<R>& visitor) = 0; …
Run Code Online (Sandbox Code Playgroud)

c++ templates virtual-functions visitor-pattern

5
推荐指数
1
解决办法
498
查看次数