6 ms·
C++17 does - it's called std::variant. std::variant<int, bool, double> options; options = true; bool value = std::get<bool>(options); bool has_bool
by andrewg 6y ago
C++17 does - it's called std::variant.
std::variant<int, bool, double> options;
options = true;
bool value = std::get<bool>(options);
bool has_bool = std::holds_alternative<bool>(options);
// or test which alternative is held
if (auto i = std::get_if<int>(&options)) {
// do something with int
} else if (auto b = std::get_if<bool>(&options)) {
// do something with bool
} else {
// do something with double
}
- nicoburns 6y agoThat's not a language feature though, right? It's just a struct containing a union and a discriminant. That means: - No pattern matching means your stuck with the awkward if-elseif-else - It doesn't check that you've accounted for every possible variant. - You can only hold one variant of each type: you can't have two variants that both contain a string. - The specific instance isn't it's own type, so you can't implement methods on it.
- TFortunato 6y agoTake a look at my reply above. Your right it isn't built into the language, but it does come with a helper method, std::visit, which does take into account that you've accounted for all possible variant types, and will throw a compile error if you didn't. You also aren't stuck with if, else-if style syntax.
- etalian 6y agoA language that I am working on has those things "built-in" (it still generates compilable C++ in the backend). I did recently add pattern matching (and not just on variants) where the above would be equivalent to: $v:|[:int, :bool, :double] = 5; $vi: = v.[:int]; $holds_int: = v.?[:int]; switch v { .[:int]$i { /std cout << "got int:" << i }; .[:bool] { /std cout << "got bool" }; .[:double]$d { /std cout << "got double: " << d }; }; If a type repeats in the same variant, you would match by index to tell them apart: $v:|[:int, :int]<(.[0] = 5); switch v { .[0]$i0 { /std cout << "got first int:" << i0 }; .[1]$i1 { /std cout << "got second int: " << i1 }; }; (I have some ideas to allow named labels instead of numerical indices but that is not yet implemented) It is, in spirit, an implementation of the inspect proposal [1], but with a (subjectively) much simpler and more powerful syntax (the grammar of the entire language is fully LALR(1) without ambiguities). [1] http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1371r1.pdf http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p137...
- pjmlp 6y agoYou can use std::visit() for the time being, and pattern matching is being discussed.
- TFortunato 6y agoThis works out really nicely when combined with variadic template tricks. (Taken from CPP Reference) // Helper for creating anonymous visitor functions template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; }; template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>; using var_t = std::variant<int, long, double, std::string>; std::vector<var_t> vec = {10, 15l, 1.5, "hello"}; // Type matching visitor for (auto& v: vec) { 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); } Outputs: 10 15 1.500000 "hello"
- zeotroph 6y agoThat does not give you destructuring though, so to distinguish different variants of the same type you are left with a classic `if` inside the lambda. Also this has "language support" in the sense that it is (again) implemented via template meta programming, i.e. the compile time is impacted quite heavily. See "std::visit is everything wrong with modern C++": https://bitbashing.io/std-visit.html https://bitbashing.io/std-visit.html This standards proposal would add proper match (named, of course, inspect) support: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0095r1.html http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p009...
- TFortunato 6y agoYes, I'm definitely not saying that std::visit is perfect by any stretch of the imagination
- dunefox 6y agoWhat a ridiculous language C++ is.