Is std::variant allowed to allocate memory for its members?
Asked Answered
S

2

27

I was wondering if an implementation of std::variant must necessarily be "flat" or whether it is allowed to dynamically allocate memory for its members, such that a sequence of variants would degenerate to a sequence of pointers, thereby destroying cache locality.

Shriner answered 18/12, 2017 at 20:36 Comment(1)
I added the word "flat" to the title as I initially searched for exactly that. I will put it in the question body, so it is searchable, while keeping the more descriptive title you proposed.Shriner
E
31

No, very explicitly. From [variant.variant]:

Any instance of variant at any given time either holds a value of one of its alternative types, or it holds no value. When an instance of variant holds a value of alternative type T, it means that a value of type T, referred to as the variant object's contained value, is allocated within the storage of the variant object. Implementations are not permitted to use additional storage, such as dynamic memory, to allocate the contained value. The contained value shall be allocated in a region of the variant storage suitably aligned for all types in Types.... It is implementation-defined whether over-aligned types are supported.

Eleonoreeleoptene answered 18/12, 2017 at 20:43 Comment(7)
Does that mean that a variant of vectors (for example) is not allowed? GCC and MSVC appear to accept this, but Clang does not: godbolt.org/g/ZZAXorMunificent
@Munificent Uh, no? It's definitely allowed. Such a restriction wouldn't make any sense, nor be enforceable. Clang rejects it because of this.Eleonoreeleoptene
Right, that makes sense now that I re-read the wording of the standard. Thanks.Munificent
The variant containing the vector isn't doing any dynamic allocation, the vector is. It's no different from having a pointer type in a variant -- you're allowed to store a pointer to dynamic memory there. @MunificentSignalize
@Barry: I'm actually quite surprised the standard contains such an explicit statement about this behavior. After all, tuple doesn't have similar wording, despite the fact that there's basically no implementation of it that would dynamically allocate storage for the members.Tedmann
@Nicol True. I guess it's strongly implied by being am extension of thepair.Eleonoreeleoptene
@NicolBolas FWIW, tuple does require For each tuple constructor, an exception is thrown only if the construction of one of the types in Types throws an exception. AFAIK, that means it can't dynamically allocate.Indentation
S
9

According to cppreference ::std::variant must not allocate dynamic memory.

As with unions, if a variant holds a value of some object type T, the object representation of T is allocated directly within the object representation of the variant itself. Variant is not allowed to allocate additional (dynamic) memory.

Shriner answered 18/12, 2017 at 20:36 Comment(7)
I’m not sure if the question is useful, especially since answer doesn’t quote standard.Downstate
@Downstate I strongly disagree. It is a very valid question with a very good answer. You don't need to always quote from standard.Madelle
@bolov, my opinion is that if it is possible to find it in one google search, it is not worth separate question and answer. Decrypting standard is quite hard though. I upvoted the new answer, and left the question intact. May be SO taught me too hard about searching on my own, dunno.Downstate
@Downstate an answer found somewhere on google does not add value to this community content in any way. I don't care if you can find the answer with google. If it is a good question, I want it here, on stackoverflow.Madelle
@Downstate if you can find the answer with google and that answer is already on stackoverflow, well, that is an entire other problem....Madelle
@bolov, if it is better documented somewhere else, then it shouldn’t be brought here. I believe it is written somewhere in the help center. But yeah, too much C++ questions are here, so maybe having them in one place is good.Downstate
I agree that I should have taken the answer directly from the standard, not cppreference. But I consider cppreference as good as the standard (and much easier to navigate).Shriner

© 2022 - 2024 — McMap. All rights reserved.