class BinExpr : Expr { std :: unique_ptr lhs , rhs ; public : BinExpr ( std :: unique_ptr lhs , std :: unique_ptr rhs ) : lhs ( std :: move ( lhs )) , rhs ( std :: move ( rhs )) {} const Expr & get_lhs () const { return * lhs ; } const Expr & get_rhs () const { return * rhs ; } }; Think of what the memory layout for this storage mechanism looks like: the vector will have a contiguous chunk of memory allocated for storing pointers to all of the nodes, then each pointer will have an associated chunk of memory the size of a node which, as mentioned earlier, varies for each kind of node. One thing to keep in mind, when storing your AST nodes like this, is that the size of each node will now be equal to the size of the largest representable node.