The pattern that a lot of people use with C++17 / boost variants looks very similar to switch statements. For example: (snippet from cppreference.com)
std::variant<int, long, double, std::string> v = ...;
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);
The problem is when you put the wrong type in the visitor or change the variant signature, but forget to change the visitor. Instead of getting a compile error, you will have the wrong lambda called, usually the default one, or you might get an implicit conversion that you didn't plan. For example:
v = 2.2;
std::visit(overloaded {
[](auto arg) { std::cout << arg << ' '; },
[](float arg) { std::cout << std::fixed << arg << ' '; } // oops, this won't be called
}, v);
Switch statements on enum classes are way more secure, because you can't write a case statement using a value that isn't part of the enum. Similarly, I think it would be very useful if a variant visitor was limited to a subset of the types held in the variant, plus a default handler. Is it possible to implement something like that?
EDIT: s/implicit cast/implicit conversion/
EDIT2: I would like to have a meaningful catch-all [](auto)
handler. I know that removing it will cause compile errors if you don't handle every type in the variant, but that also removes functionality from the visitor pattern.
char
). – Reenareenforcedefault
in yourswitch
, you have the same issue. (which is the equivalent ofauto arg
here). – Retributiveelse
statement is a compile time error... I don't see what you want to do that this version does not? – Reenareenforcefloat
and addingstd::vector<float>
for the compiler? – Reenareenforceenum class
, then write a non-exhaustiveswitch
on it with adefault
handler. Then change the name of an element in the enum that you have acase
statement for. It causes a compile error, I want the same thing here. – Stanfordvariant
. – Retributivestatic_assert
at the beginning of the lambda to check for only possible types. – Reenareenforce