Trying to get more familiar with C++17, I've just noticed std::visit
:
template <class Visitor, class... Variants>
constexpr /*something*/ visit(Visitor&& vis, Variants&&... vars);
Why does std::visit
not take a single variant, but rather any number of variants? I mean, you can always take some standard library function and have it take multiple parameters with the same role, working on all of them (e.g. std::find()
for multiple elements in a container); or you could be taking multiple visitors and using them on the same variant.
So, why this specific 'variadification'?
To make multiple visitation cleaner. Let's say I had two
std::variant<A,B>
, one namedleft
and one namedright
. With multiple visitation, I can write:That's a pretty clean interface, and is something that's pretty commonly useful. It's also easy to implement efficiently - you just create a n-dimensional array of functions instead of a one dimensional array.
On the other hand, with only single visitation, you'd have to write:
That's miserable to write, miserable to read, and likely less efficient too.
Because we need to allow for visitation of combinations of classes within variants. That is, if we have
we can obviously use these kinds of visitors:
with
Var1
andVar2
respectively. We can even use this next kind, with bothVar1
andVar2
individually:but what OP is missing is that we want to be able to visit one of the four pairs
(A,C)
,(A,D)
,(B,C)
,(B,D)
- when looking at a pair ofVar1
andVar2
together. That's why the variadic argument tostd::visit
is all-but-necessary. An appropriate visitor would look like this:and we would call
std::visit(Visitor4{}, my_var1_instance, my_var2_instance);
I figured this out when reading Barry's answer.