3
\$\begingroup\$

I'm currently working through the "Crafting Interpreters" book by Robert Nystrom. He uses Java to implement the visitor pattern in which the visitor functions return the Object type. C++ doesn't support an Object type so my solution was to create a polymorphic type in c++ using virtual functions and inheritance

I'm just curious about the drawbacks of my implementation and how it could be implemented better:

#include <iostream>
#include <string>

class Object {
public:
    virtual std::string getType() const = 0;
};

class String : public Object {
private:
    std::string value;

public:
    String(const std::string& val) : value(val) {}

    std::string getType() const override {
        return "string";
    }

    std::string getValue() const {
        return value;
    }
};

class Double : public Object {
private:
    double value;

public:
    Double(double val) : value(val) {}

    std::string getType() const override {
        return "double";
    }

    double getValue() const {
        return value;
    }
};

\$\endgroup\$

1 Answer 1

3
\$\begingroup\$

Use std::variant instead

With your code you have to write a visitor like this:

Object* object = new Double(3.1415);

if (object->getType() == "string") {
    std::cout << static_cast<String*>(object)->getValue();
} else if (object->getType() == "double") {
    std::cout << static_cast<Double*>(object)->getValue();
}

Which is very tedious (especially as you add more types), inefficient, and doesn't have type safety, as you can accidentally static_cast<>() to the wrong type and the compiler won't notice. You also need to work with pointers a lot, which means you have to be careful to delete them where appropriate, or use the right smart pointers.

C++17 introduced std::variant to solve this in a type safe way, and allows for an easier way to visit it. For example, you can write:

using Object = std::variant<std::string, double>;
…
Object object = 3.1415;

std::visit([](auto& value) {
    std::cout << value;
}, object);
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.