Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

std::variant vs std::any when type is move constructible

If I have a type that is std::is_nothrow_move_constructible and I need to store it in a std::any or std::variant, which one would you recommend to use and why? Which one will give the least overhead? Edit: What are the different use cases for std::variant vs std::any?

class MyType
{
public:
   MyType(const MyType&) = default;
   MyType(MyType&&) = default;
   MyType() = default;
};

int main(int argc, char* argv[])
{
   static_assert(std::is_nothrow_move_constructible<MyType>::value, "Not move constructible");
   return 0;
}
like image 975
0xBADF00 Avatar asked Sep 05 '17 10:09

0xBADF00


3 Answers

If you know the types, use std::variant. In that case you know all the possible types, and use std::variant::visit() to apply the visitor to the variants.

If you don't, use std::any. You can think about this when dealing with types that are generic. In other words, when the types are not known apriori.


Which one will give the least overhead?

std::variant, cannot use the heap. It's not allowed to. There is no way to actually have a structure containing a possible variant of itself without a dynamic allocation, as such a structure can easily be shown to be infinite in size if statically declared. Source.

In contrast, std::any may do so. As a result, the first will have faster construction and copy operations.

like image 104
gsamaras Avatar answered Nov 18 '22 21:11

gsamaras


std::any allocates the storage for the value from the heap. Whereas std::variant does not use the heap, hence it is more efficient in terms of construction and copy and more cache friendly because the value stored directly in the object and it does not involve indirection and virtual functions to access it.

The interface of std::variant is richer and easier to use.

std::any is useful only when std::variant cannot be used for some reason.

like image 37
Maxim Egorushkin Avatar answered Nov 18 '22 20:11

Maxim Egorushkin


For reasons of type safety, loose coupling and ease of maintenance:

prefer variant over any if you possibly can.

Because in essence, std::any is sugar-coating around a cloneable std::unique_ptr<void, some_deleter>.

Which has a little bit of protection around bad casts (it'll throw rather than crash, which in many programs amounts to the same thing).

like image 23
Richard Hodges Avatar answered Nov 18 '22 20:11

Richard Hodges