What are the advantages of using std::variant as opposed to traditional polymorphic processing?
Asked Answered
G

2

8

Suppose I have a Shape base class and Circle, Line, and Point derived classes. I have two functions.

std::variant<Circle, Line, Point> process(const Shape &s);
Shape process(const Shape& s);

I can pass in any of my derived classes and return a Shape object in the second function, a variant is just a union that can hold any of my derived class variables at any given time.

Now with std::variant I can also employ a visitor where I can process some function depending on what type my variant is currently holding (I could just create a function object and pass it std::transform and apply it to each of my objects). However, I can just make that function virtual in my base class and have each derived class implement it.

So, is variant just a convenience?

Grackle answered 12/9, 2018 at 13:54 Comment(9)
You seem to be under the impression that std::variant's template arguments must share a common base. You can store unrelated types in an std::variant.Heartburn
imho too broad, though the most obvious is that you can put any types into a variant, while you cannot use a Circle and a Rectangle polymorphically, unless they both inherit Shape, thats a small but big differenceHeighho
eg std::variant<int,double,std::string>, no chance to get anywhere close to that via inheritanceHeighho
FWIW: Shape process(const Shape& s) isn't the same as std::variant<Circle, Line, Point> process(const Shape &s) as the former slices the object. You need to return by reference/smart pointer/pointer.Included
@user463035818 "no chance": You could define wrapper classes around with common base class. Close to? I'd say so - maybe.... Ugly? Sure...Eternize
@Eternize But then you wouldn't have a std::variant<int,double,std::string> anymore.Included
Nice comparison is here: Inheritance vs std::variantRidgley
@Eternize yeah i was expecting someone to disagree. Replace "no chance to get anywhere close to" as "it would be so tedious and not nice that you wouldnt usually consider it as an option" and I guess we can agree ;)Heighho
@user463035818 Sure... Hm, and I must admit I did not consider aesthetics being a potential measure for distance - with that one, it would get quite large...Eternize
M
15

So, is variant just a convenience?

No, they are different concepts. Main difference that on one side std::variant can work with unrelated types including builtins like int which is not possible with virtual functions directly. On another side std::variant must know types it is working with at compile time. For example it is possible to add a type with virtual function(s) by just linking additional object module without recompiling rest of the code or loading a shared library dynamically to existing application (you do not even have to restart the app) while with std::variant you must recompile code dealing with types std::variant contains.

Marcelo answered 12/9, 2018 at 14:7 Comment(0)
A
4

However, I can just make that function virtual in my base class and have each derived class implement it.

Yes.... if all the elements in the variant share a common Base (which Slava already mentioned).

Another big difference is that, with a variant, there's not necessarily any dynamic polymorphism happening at all (no RTTI needed) during visitation.

In conjunction with std::visit, there are a lot of tricks under the hood to make sure that there's (basically) zero runtime overhead in calling the appropriate function for a given std::variant. Although there could be non-trivial additional compile time and memory usage because it does this by creating a big matrix of function pointers (See this excellent blog post from Michael Park about it)

Afire answered 12/9, 2018 at 14:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.