Bug 1845 – Variant and VariantN cannot handle structs of arbitrary size

Status
RESOLVED
Resolution
FIXED
Severity
enhancement
Priority
P2
Component
phobos
Product
D
Version
D2
Platform
x86
OS
Linux
Creation time
2008-02-16T15:38:00Z
Last change time
2015-06-09T01:14:30Z
Assigned to
andrei
Creator
dhasenan

Comments

Comment #0 by dhasenan — 2008-02-16T15:38:08Z
Variant can only handle structs and static arrays of at most 2 * sizeof(size_t) bytes. VariantN can handle structs and static arrays of any specified size. This is intended behavior. However, it wastes memory: if I know I might need to store a struct of 64 bytes, then I'll store a char with 63 bytes of padding. If I am writing a library, I cannot use Variant or VariantN because I do not know what size structs the end user might want to use. I could store an array of VariantN and, if I need to store something larger than the current maximum size, copy everything into another array of VariantN with a larger maximum size. I'd have to store this array in a Variant, as well, since its type will continue to change. But that's just silly. Variant is supposed to be a solution for boxing, so I shouldn't have to concern myself with size. At least, I should be able to avoid those concerns, even if they are exposed. For comparison, Tango stores large structs on the heap, and can store arbitrarily large structs.
Comment #1 by andrei — 2008-02-16T16:23:41Z
The intent was to not inflict heap allocation on Variant's user unwittingly. If large structs are to be stored in a Variant, they should be stored by pointer and allocated in user code. However, transparent pointer storage has its appeal too. I'd like to collect more use cases before changing the implementation. All -- please advise.
Comment #2 by dsimcha — 2009-04-05T16:40:27Z
I'd say the best compromise between a well-encapsulated solution and a solution that avoids hidden allocations is to have something like a bigAssign(T) method in addition to the regular opAssign. It would work something like this: struct Huge { real a, b, c, d, e, f, g; } void main() { Huge huge; Variant v; v = huge; // Compile time error. v.bigAssign(huge); // Works, allocates on heap transparently. v.bigAssign(5); // Works, equivalent to v = 5 or v.opAssign(5). } Heck, you could even make this a policy. Let's say you have two functions: neverAllocate() and allocateAsNeeded(). You could make opAssign() an alias to one of these instead of a funciton. The VariantN template could take an alias parameter for opAssign that defaults to one of the two, but can be overridden on instantiation. Not sure which the default should be, but that's a minor detail.
Comment #3 by andrei — 2009-08-25T00:40:25Z
Fix coming in the next release.