I’m writing a small C compiler front-end in C++17 as a learning project.
My parser builds an AST for expressions, and I’m not sure about the best way to handle ownership for child nodes.
Here is a minimal example:
#include
enum class NodeKind { IntegerLiteral, BinaryExpr };
enum class BinaryOp { Add, Sub };
struct Node {
NodeKind kind;
virtual ~Node() = default;
};
struct IntegerLiteral : Node {
int value;
explicit IntegerLiteral(int v) : value(v) {
kind = NodeKind::IntegerLiteral;
}
};
struct BinaryExpr : Node {
BinaryOp op;
Node* lhs; // raw pointers for now
Node* rhs;
BinaryExpr(BinaryOp op, Node* lhs, Node* rhs)
: op(op), lhs(lhs), rhs(rhs) {
kind = NodeKind::BinaryExpr;
}
~BinaryExpr() {
delete lhs;
delete rhs;
}
};
Parser code (simplified):
Node* parseAdditiveExpr() {
Node* left = parsePrimaryExpr();
while (/* see + or - */) {
BinaryOp op = /* ... */;
Node* right = parsePrimaryExpr();
left = new BinaryExpr(op, left, right);
}
return left;
}
This works but is fragile (manual delete, exception safety)
I’d like to convert this to use std::unique_ptr
Question:
Given this simplified AST, what is the idiomatic way in C++17 to: store child nodes as std::unique_ptr