3 ms·
std::variant is an abomination that should never be used by anyone ever. Everything about it is sooooo bad.
by forrestthewoods 1y ago
std::variant is an abomination that should never be used by anyone ever. Everything about it is sooooo bad.
- nrclark 1y agoout of curiosity, can you elaborate on that a bit? I've shipped std::variant in a few designs and it's been OK, but maybe I didn't use it deeply enough to see issues.
- coffeeaddict1 1y agoIt doesn't have proper pattern matching (you have to use a visitor class or the weird overload trick), and it sucks for compile times. It should have been a language construct rather than adding it to std, but the committee is often too scared to touch the language because they are stubbornly unwilling to break backwards compatibility.
- tialaramex 1y agoC++ is a proud New Jersey language. So the priority has been and continues to be ease of implementation. If it's tricky to make it work right, don't sweat it - the users (in this case that's us programmers) will put up with it not working right. std::variant has valueless_by_exception - the C++ language wasn't able to ensure that your variant of a Dog or a Cat is always, in fact, a Dog or a Cat, in some cases it's neither so... here's valueless_by_exception instead, sorry.
- Maxatar 1y agoEase of implementation was not the issue here, on the contrary the easier implementation would have guaranteed that std::variant<Dog, Cat> always contains a Dog or a Cat. The issue was performance in that guaranteeing a Dog or a Cat requires dynamic storage duration if either of Dog or Cat has a throwing constructor. If neither Dog or Cat have throwing constructors, then std::variant<Dog, Cat> is guaranteed to always be a Dog or a Cat.
- tialaramex 1y ago> The issue was performance in that guaranteeing a Dog or a Cat requires dynamic storage duration if either of Dog or Cat has a throwing constructor. Any need here for an allocator is due to a language defect. Rather than implement a fix for the C++ programming language they just punted this problem to every C++ programmer. That's the New Jersey style.
- spacechild1 1y agoThat's a bit hyperbolic. Sure, it's not exactly ergonomic, but that doesn't mean I can't use it. One thing that bugs me is that there is still no overload helper in the standard: // helper type for the visitor template<class... Ts> struct overloads : Ts... { using Ts::operator()...; }; Of course, having true pattern matching would be much nicer. At least there's a proposal: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2688r3.html https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p26...
- forrestthewoods 1y agoI will boldly state that std::variant makes all code worse and it is always better to not use it. I love sum types in Rust. They’re great. This stuff exists solely to add ergonomics. If it’s not ergonomic it’s just making your code worse! std::variant is fundamentally broken because it uses types as its discriminant. Want a variant with two ints that represent two things? Fuck you, you can’t. Rust enums of course can do this. std::visit is an abomination. As is the template overloaded bullshit you have to copy paste into projects. And of course the error messages when you get when it’s wrong are atrocious even by C++ standards. No. std::variant is awful and you should simply never use it. This could change in 2040 when you can use C++32. But for now just avoid it.
- Maxatar 1y ago>Want a variant with two ints that represent two things? Fuck you, you can’t. This is false, I also find that in general you have a tendency to make false claims about C++ in most of your posts about it. I would suggest you check out a resource like https://en.cppreference.com/ https://en.cppreference.com/ just as a sanity check before you make claims about the language in the future, and also because it's a very good resource for learning the ins and outs of the language. As for your claim, std::variant supports index based discrimination similar to std::tuple, so you can absolutely have a std::variant<int, int>, and access the second int along the lines of: auto foo = std::variant<int, int>(); std::get<1>(foo) = 123; std::cout << std::get<1>(foo); This is all documented with examples: https://en.cppreference.com/w/cpp/utility/variant/get.html https://en.cppreference.com/w/cpp/utility/variant/get.html
- SJC_Hacker 1y agoKill me, but I never saw the point over abstract base classes and polymorphic behavior defined in the subclasses. Now purists will scream “compile time optimization!”, but in reality std::variant is inplemeted very múch líne a vtable. There was a good talk at Cppcon a few years ago on this issue. In particular, they found no difference in performance.
- aw1621107 1y ago> Kill me, but I never saw the point over abstract base classes and polymorphic behavior defined in the subclasses. They're different tools which can fit different situations better or worse. std::variant fits some situations better (e.g., expressing a known closed set of types which may or may not share a common interface - tree nodes, option/result types, state machines, etc.), while interfaces/virtual functions fit some other situations better (e.g., expressing a potentially-open set of types with a shared interface - widget hierarchies, type erasure, etc.). > Now purists will scream “compile time optimization!” I actually feel like under most circumstances it's how closely one option or the other matches your problem domain that influences the decision one way or the other, not performance. In any case, it doesn't really help that std::variant is somewhat neutered in C++ by a rather awkward interface as well as the lack of generalized/ergonomic pattern matching such as that offered by Haskell/ML-likes/Rust.