Inheritance
I believe that inheritance based OOP is painful to use in C++ compared to languages like java. In my opinion, static polymorphism is better. Runtime polymorphism is hard to do because C++ has manual memory (and ownership semantics in general) and local variables are strongly typed.
Use cases
Personally I can't see a use case for visitor. They might be useful in conjunction with std::variant
, but otherwise I fail to see it being useful.
Too much runtime
If a function is virtual, there is no need to store it in std::function
. Too many indirections, and the last one has type erasure, which is heavier mechanism than runtime polymorphism.
Static way
Visitors are usually used to get double dispatch. Templates provide N way dispatch, e.g. the type will keep propagating as long as the call chain is all templated. Lets look at this interesting example from std::visit documentation page.
template<class... Ts> struct overloaded : Ts... {
template <class... Fs> overloaded(Fs&&... fs) :
Ts{std::forward<Fs>(fs)}...
{}
using Ts::operator()...;
};
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
This requires C++17, but not hard to emulate using C++14, using make_overloaded
.
Now, the usage:
std::visit(overloaded {
[](auto arg) { std::cout << arg << ' '; },
[](double arg) { std::cout << std::fixed << arg << ' '; },
[](const std::string& arg) { std::cout << std::quoted(arg) << ' '; },
}, v); // v is std::variant
As you can see, types are actually inferred, so the need for std::function
just goes away. Usually, templates are good way to go unless it is some highly dynamic environment like GUI, where I would pick Qt framework or, for a language, python, or any other duck typed language.