树突变和共享指针问题的访问者模式

Visitor pattern for tree mutation and shared pointer problem

我正在尝试为 n 元树变异实现访问者模式。目前我坚持使用共享指针。 Mutator 对每个树节点进行操作,并且可以 return 指向节点本身的指针 w/o 任何更改,或者指向修改节点副本的指针(不能直接修改原始节点)。但显然我不能从 Visit 方法内的原始指针构建共享指针,我也不能从 Mutate 方法内的 this 创建共享指针。我想到的唯一想法是创建另一个 class 来保存指针并将此 class 指针传递给访问者,但也许有更好的解决方案?


// Forward declarations
class ExpressionTreeMutator;

struct BaseExpr;

enum class ExpressionType {
  kString,
  kInt,
};

using ExprPtr = std::shared_ptr<BaseExpr>;

struct BaseExpr {
  explicit BaseExpr(ExpressionType expression_type) : expression_type_(expression_type) {}

  virtual ~BaseExpr() = default;

  virtual ExprPtr Mutate(ExpressionTreeMutator* visitor) const = 0;

  ExpressionType expression_type_;
};

// Curiously recurring template pattern
template<typename T>
struct Expr : public BaseExpr {
  explicit Expr(ExpressionType expression_type) : BaseExpr(expression_type) {}

  ~Expr() override = default;

  ExprPtr Mutate(ExpressionTreeMutator* visitor) const override;
};

struct String : public Expr<String> {
  explicit String(std::string value) : Expr(ExpressionType::kString),
                                       value_(std::move(value)) {}

  std::string value_;
};

struct Int : public Expr<Int> {
  explicit Int(int64_t value) : Expr(ExpressionType::kInt),
                                value_(value) {}

  int64_t value_;
};

class ExpressionTreeMutator {
public:
  virtual ~ExpressionTreeMutator() = default;

protected:
  template<typename T>
  friend
  struct Expr;

  virtual ExprPtr Visit(Int const* expr) {
//    return expr ??? (in some cases return ptr as it is)
  };

  virtual ExprPtr Visit(String const* expr) {
//     return String::Make(expr) ??? (make a copy)
  };
};

template<typename T>
ExprPtr Expr<T>::Mutate(ExpressionTreeMutator* visitor) const {
  return visitor->Visit(dynamic_cast<T const*>(this));
}

因为它被标记为 C++20,所以我建议改用 std::variant 和 std::visit。

否则,您可以从 std::enable_shared_from_this 继承,这允许从 X 的方法中创建 shared_ptr。

您也可以使用 mutate 不进行实际的突变,而是 return 进行突变的适当函数对象,然后将 shared_ptr 传递给该对象。