树突变和共享指针问题的访问者模式
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 传递给该对象。
我正在尝试为 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 传递给该对象。