20

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.

bitmask
  • 25,740
  • 12
  • 80
  • 142
  • 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. – bitmask Dec 18 '17 at 21:01

2 Answers2

24

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.

Barry
  • 247,587
  • 26
  • 487
  • 819
  • Does that mean that a variant of vectors (for example) is not allowed? GCC and MSVC appear to accept this, but Clang does not: https://godbolt.org/g/ZZAXor – 0x5453 Dec 18 '17 at 21:51
  • 2
    @0x5453 Uh, no? It's definitely allowed. Such a restriction wouldn't make any sense, nor be enforceable. Clang rejects it because of [this](https://stackoverflow.com/q/46506387/2069064). – Barry Dec 18 '17 at 22:07
  • Right, that makes sense now that I re-read the wording of the standard. Thanks. – 0x5453 Dec 18 '17 at 22:16
  • 6
    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. @0x5453 – Barmar Dec 19 '17 at 00:58
  • 1
    @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. – Nicol Bolas Dec 19 '17 at 05:12
  • @Nicol True. I guess it's strongly implied by being am extension of the`pair`. – Barry Dec 19 '17 at 14:10
  • 3
    @NicolBolas FWIW, `tuple` does [require](https://timsong-cpp.github.io/cppwp/tuple#cnstr-2) *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. – NathanOliver Jan 08 '19 at 22:01
7

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.

bitmask
  • 25,740
  • 12
  • 80
  • 142
  • 1
    I’m not sure if the question is useful, especially since answer doesn’t quote standard. – Incomputable Dec 18 '17 at 20:39
  • 5
    @Incomputable I strongly disagree. It is a very valid question with a very good answer. You don't need to always quote from standard. – bolov Dec 18 '17 at 20:41
  • @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. – Incomputable Dec 18 '17 at 20:43
  • @Incomputable 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. – bolov Dec 18 '17 at 20:47
  • @Incomputable if you can find the answer with google and that answer is already on stackoverflow, well, that is an entire other problem.... – bolov Dec 18 '17 at 20:49
  • @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. – Incomputable Dec 18 '17 at 20:49
  • 2
    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). – bitmask Dec 18 '17 at 20:59