I'd like to create a hierarchy of visitors to handle instances of std::variant
. I'd like to override some of the methods in subclasses for more specialized behavior. My code looks like this:
#include <variant>
#include <cstdint>
#include <iostream>
struct Event1 {};
struct Event2 {};
using Event = std::variant<Event1, Event2>;
class Visitor {
public:
virtual ~Visitor() = default;
virtual void operator()(const Event1&) { std::cout << "Visitor: Event1\n"; }
virtual void operator()(const Event2&) { std::cout << "Visitor: Event2\n"; }
};
class SubVisitor: public Visitor {
public:
using Visitor::operator();
virtual void operator()(const Event1&) { std::cout << "SubVisitor: Event1\n"; }
};
int main() {
SubVisitor sv;
Event e;
e = Event1{};
std::visit(sv, e);
e = Event2{};
std::visit(sv, e);
}
This compiles and seems to work fine:
$ g++ test.cpp -o test
$ ./test
SubVisitor: Event1
Visitor: Event2
Is such code well defined and carry no risk of an undefined behavior? All examples of std::variant
I've seen use either simple classes with no inheritance or lambdas.
Yes, such code is required to do what you expect. When you pass a Visitor &
to std::visit
, it won't copy (and thus slice) it.
All examples of std::variant I've seen use either simple classes with no inheritance or lambdas.
That's because examples tend to be as simple as possible.