Smart Pointers

virtual_ptr can also be used in combination with smart pointers. virtual_ptr<std::shared_ptr<Class>> (aliased to shared_virtual_ptr<Class>) and virtual_ptr<std::unique_ptr<Class>> (aliased to unique_virtual_ptr<Class>) deliver the convenience of automatic memory management with the speed of virtual_ptr. Convenience functions make_shared_virtual and make_unique_virtual create an object and return a smart virtual_ptr to it. Since the exact type of the object is known, the vptr is read from a static variable, without incuring the cost of a hash table lookup.

Here is a variation of the AST example that uses dynamic allocation and unique pointers:

#include <iostream>
#include <memory>

#include <boost/openmethod.hpp>
#include <boost/openmethod/unique_ptr.hpp>
#include <boost/openmethod/compiler.hpp>

using namespace boost::openmethod::aliases;

struct Node {
    virtual ~Node() {}
};

struct Literal : Node {
    Literal(int value) : value(value) {}

    int value;
};

struct Plus : Node {
    Plus(unique_virtual_ptr<Node> left, unique_virtual_ptr<Node> right)
        : left(std::move(left)), right(std::move(right)) {}

    unique_virtual_ptr<Node> left, right;
};

struct Negate : Node {
    Negate(unique_virtual_ptr<Node> node) : child(std::move(node)) {}

    unique_virtual_ptr<Node> child;
};

BOOST_OPENMETHOD(value, (virtual_ptr<Node>), int);

BOOST_OPENMETHOD_OVERRIDE(value, (virtual_ptr<Literal> node), int) {
    return node->value;
}

BOOST_OPENMETHOD_OVERRIDE(value, (virtual_ptr<Plus> node), int) {
    return value(node->left) + value(node->right);
}

BOOST_OPENMETHOD_OVERRIDE(value, (virtual_ptr<Negate> node), int) {
    return -value(node->child);
}

BOOST_OPENMETHOD_CLASSES(Node, Literal, Plus, Negate);

auto main() -> int {
    boost::openmethod::initialize();

    auto expr = make_unique_virtual<Negate>(
        make_unique_virtual<Plus>(
            make_unique_virtual<Literal>(1),
            make_unique_virtual<Literal>(2)));

    std::cout << value(expr) << "\n"; // -3

    return 0;
}