digitalmars.D.learn - Variant and immutable struct
- Vlad Leberstein (27/27) Jan 05 2016 Hi!
- Vlad Leberstein (101/117) Jan 10 2016 Okay, I've cleared up some misconception.
- =?UTF-8?B?w5hpdmluZA==?= (3/11) Aug 21 2016 I am hitting the same problem. Trying to send an immutable
Hi! I've stumbled into some strange problem. I'm trying to put an immutable struct into std.variant.Variant but get some compilation error(but only when struct has at least one member). Stripped down example(tested on Linux dmd64 v2.069.2): import std.variant : Variant; immutable struct Test { int member; } int main() { Test v; Variant test = v; return 0; } Stacktrace: /usr/include/dmd/phobos/std/variant.d(311,25): Error: cannot modify struct *zat Test with immutable members /usr/include/dmd/phobos/std/variant.d(630,21): Error: template instance std.variant.VariantN!32LU.VariantN.handler!(Test) error instantiating /usr/include/dmd/phobos/std/variant.d(546,17): instantiated from here: opAssign!(Test) src/app.d(95,10): instantiated from here: __ctor!(Test) The same happens with immutable class(there is related thread with workaround at http://www.digitalmars.com/d/archives/digitalmars/D/learn/Sending_an_immutable_object_to_a thread_73866.html), but not with immutable primitives(e.g. immutable int). Is this a bug or just my misunderstanding? Thanks in advance!
Jan 05 2016
Okay, I've cleared up some misconception. On Wednesday, 6 January 2016 at 03:22:47 UTC, Vlad Leberstein wrote:The same happens with immutable class(there is related thread with workaround at http://www.digitalmars.com/d/archives/digitalmars/D/learn/Sending_an_immutable_object_to_a_thread_73866.html)This is irrelevant here. On Wednesday, 6 January 2016 at 03:22:47 UTC, Vlad Leberstein wrote:I'm trying to put an immutable struct into std.variant.Variant but get some compilation error(but only when struct has at least one member). Stripped down example(tested on Linux dmd64 v2.069.2): import std.variant : Variant; immutable struct Test { int member; } int main() { Test v; Variant test = v; return 0; }Qualifier applied to definition of aggregate type just marks all it's members with the qualifier and doesn't change the type itself(as I thought initially). So the problem with current implementation of std.variant.Variant is that it tries to modify(from the point of view of Type System) existing struct instance containing immutable members. I've done a little bit of hacking on Variant and came up with the following modification of "tryPutting": ... static bool tryPutting(A* src, TypeInfo targetType, void* target) { alias UA = Unqual!A; alias MutaTypes = TypeTuple!(UA, ImplicitConversionTargets!UA); alias ConstTypes = staticMap!(ConstOf, MutaTypes); alias SharedTypes = staticMap!(SharedOf, MutaTypes); alias SharedConstTypes = staticMap!(SharedConstOf, MutaTypes); alias ImmuTypes = staticMap!(ImmutableOf, MutaTypes); static if (is(A == immutable)) alias AllTypes = TypeTuple!(ImmuTypes, ConstTypes, SharedConstTypes); else static if (is(A == shared)) { static if (is(A == const)) alias AllTypes = SharedConstTypes; else alias AllTypes = TypeTuple!(SharedTypes, SharedConstTypes); } else { static if (is(A == const)) alias AllTypes = ConstTypes; else alias AllTypes = TypeTuple!(MutaTypes, ConstTypes); } foreach (T ; AllTypes) { if (targetType != typeid(T)) { continue; } static if (is(typeof(*cast(T*) target = *src))) { T* zat = cast(T*) target; if (src) { assert(target, "target must be non-null"); *zat = *src; } } else static if ((is(T == const(U), U) || is(T == shared(U), U) || is(T == shared const(U), U) || is(T == immutable(U), U)) && is(typeof(*(cast(U*) (target)) = *(cast(UA*) src))) ) { U* zat = cast(U*) target; if (src) { assert(target, "target must be non-null"); *zat = *(cast(UA*) (src)); } } else static if(is(T == struct)) { if (src) { assert(target, "target must be non-null"); memcpy((cast(void*) target), (cast(const(void*)) src), A.sizeof); } } else { // type is not assignable if (src) assert(false, A.stringof); } return true; } return false; } ... As I'm not very good at D, I would like to get some feedback about this solutions' viability. AFAIU memcpy-ing struct here is safe because all target arguments ever passed to tryPutting are internal to implementation(and SHOULD be void-initialized but it's currently not working AFAIK). Maybe postblit should also be called for new instance, but I'm not sure about current state of qualified postblit. Any help would be greatly appreciated!
Jan 10 2016
On Sunday, 10 January 2016 at 17:50:44 UTC, Vlad Leberstein wrote:As I'm not very good at D, I would like to get some feedback about this solutions' viability. AFAIU memcpy-ing struct here is safe because all target arguments ever passed to tryPutting are internal to implementation(and SHOULD be void-initialized but it's currently not working AFAIK). Maybe postblit should also be called for new instance, but I'm not sure about current state of qualified postblit. Any help would be greatly appreciated!I am hitting the same problem. Trying to send an immutable hashmap of variants with std.concurrency.
Aug 21 2016