shallow copy of const(Object)[]

Jonathan M Davis via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Fri Oct 31 17:08:13 PDT 2014


On Friday, October 31, 2014 18:38:59 anonymous via Digitalmars-d-learn wrote:
> I have a const(Object)[] and I want a shallow copy of the array.
> .dup doesn't do it, which I thought a bug, but according to
> Martin Nowak it's by design [1].
> std.array.array fails, too. Is there really nothing in phobos for
> this?
>
> static import std.array;
> void main()
> {
>       const(Object)[] a;
>
>       version(dup) auto b = a.dup;
>       /* Nope. Apparently, dup is supposed to convert the elements
> to mutable [1],
>       which doesn't work with const(Object), of course. */
>
>       version(array) auto c = std.array.array(a);
>       /* Nope. Tries to convert to mutable, too? */
>
>       version(meh)
>       {
>           typeof(a) d;
>           d.reserve(a.length);
>           foreach(e; a) d ~= e;
>       }
> }
>
> [1]
> https://github.com/D-Programming-Language/druntime/pull/1001#discussion_r196
> 74927

So, by shallow copy, you mean that you want an array that contains the same
elements but is a new array? If that's what you want, just slice the array.

auto b = a[];

Sure, they'll point to the same spot in memory still, but because all of the
elements are const, you can't mutate them, so it really doesn't matter. All it
affects is that because both arrays have the same block of memory after them,
appending to one of them would make it so that appending to the other would
force it to reallocate. For for most intents and purposes, you essentially
have two different arrays.

As for std.array.array, I suspect that the problem is that it's using emplace
internally, and that isn't playing well with const. Certainly, that's what the
second error message that you get when you try looks like

/usr/include/D/phobos/std/conv.d(3844): Error: template instance 
std.conv.emplaceImpl!(const(Object)).emplaceImpl!(const(Object)) error 
instantiating

I'd have to dig into it further to see why though. But if you absolutely must
have the two arrays referring to separate blocks of memory (though I don't see
why you would), then you could always just build a new array yourself by doing
something like

    const(Object)[] a;
    const(Object)[] b;
    b.reserve(a.length);
    foreach(e; a)
        b ~= e;

You should probably create a bug report for std.array.array though, since it
arguably should work. At minimum, it could do something like that code sample,
though that's obviously not ideal in comparison to doing something like using
emplace. I'm not sure what the restrictions on emplace with regards to const
and immutable are though. Certainly, it's harder to support them, since you
can't overwrite const or immutable elements in an array.

- Jonathan M Davis



More information about the Digitalmars-d-learn mailing list