Problem with const correctness

Dan dbdavidson at yahoo.com
Sat Dec 8 13:47:31 PST 2012


On Friday, 7 December 2012 at 14:18:50 UTC, Gor Gyolchanyan wrote:
> Consider this example:
> I enforce value-type semantics by duplicating the arrays on 
> copy, so it
> should behave like a value type with no indirections 
> (implicitly convert to
> immutable).
> What do I need to do for this to work?

My approach is to have a general dup function. I call it gdup, 
for global dup so the name does not conflict with the existing 
dup. It dup's fields recursively. Feel free to have a look and 
any suggestions appreciated. Would greatly appreciate if seasoned 
D developers like (Ali,  bearophile, ...) would review - as I use 
these mixins to simplify development with structs.

https://github.com/patefacio/d-help/tree/master/d-help/opmix
docs at 
https://github.com/patefacio/d-help/blob/master/doc/canonical.pdf

Since the gdup makes all new deep copies (as dup should) the cast 
to immutable is safe. For reference structs with aliasing you 
have to worry about assignment of immutable to mutable and the 
reverse. Due to transitive immutability, both are disallowed 
without something special. dup, idup and gdup in general serve 
that purpose.

As Ali points out, I also don't think you need the opAssign at 
all in this case - since default opAssign calls postblit (which 
is nice). To get value semantics just implement postblit. If you 
add fields you should not need to worry about it.

As others pointed out - you want deep copy on the items in the 
array for your custom ctor. Since gdup is recursive and does not 
require the composed structs to have a postblit - it works even 
on arrays of T where T has aliasing but no postblit.

Thanks,
Dan

import std.stdio;
import std.traits;
import opmix.mix;

struct Array(Type_)
{
public:
   mixin(PostBlit);
   this(Type_[] array...) {
     _array = array.gdup;
   }
private:
   Type_[] _array;
}

unittest
{
   {
     Array!int one = Array!int(1, 2, 3, 4, 5);
     immutable Array!int two = cast(immutable)one.gdup;
     assert(two._array.ptr != one._array.ptr);
     assert(two._array == one._array);
   }

   {
     struct S {
       // look ma' no postblit
       char[] c;
     }
     Array!S one = Array!S(S(['d']), S(['o','g']), 
S(['b','o','y']));
     auto immutable two = cast(immutable)one.gdup;

     // Ensure the copy was deep (i.e. no sharing)
     
assert(cast(DeepUnqual!(typeof(two._array.ptr)))two._array.ptr !=
            one._array.ptr);
     assert(typesDeepEqual(two, one));
   }

}


More information about the Digitalmars-d mailing list