dynamic arrays of immutable question: Are the elements actually mutable
monarch_dodra
monarchdodra at gmail.com
Wed Jan 9 05:38:13 PST 2013
On Wednesday, 9 January 2013 at 12:38:13 UTC, Jonathan M Davis
wrote:
>
> When you append to array, the elements being added are in
> untyped memory. So,
> no mutation of immutable anything is going on at all.
Ok, I guess that makes sense.
> I don't know what Appender is doing, but casting away immutable
> and mutating
> anything is undefined behavior. However, if you _know_ that the
> data is
> actually mutable, then you can get away with it. It's still
> technically
> undefined behavior though. Pretty much the only place that it
> would make sense
> to do that that I can think of is with std.concurrency, but
> again, I don't
> know what Appender is doing.
Hum...
Appender uses "arr.length = arr.capacity" so as to mark the array
as "used" so that if anybody tries to append to the array, it
will not interfere with appender. Does this operation "make the
memory typed"?
Here is a reduced test case of what appender does
http://dpaste.dzfl.pl/d8fce486
//----
import std.stdio;
void main()
{
//The initial array
immutable(int)[] arr1 = [0, 1, 2, 3];
//The same array, aliased as mutable;
int[] arr2 = cast(int[])arr1;
//Change underlying range size so that other appends to arr1
cause relocation
size_t capacity = arr1.capacity;
if (capacity > arr1.length)
{
auto tmp = arr2;
tmp.length = tmp.capacity;
assert(arr2.ptr == tmp.ptr);
assert(arr1.capacity == 0);
}
else
assert(0); //To make sure we are actually testing
something
//Write to the not yet written but reserved to zone
for ( ; arr2.length < capacity; )
{
immutable len = arr2.length;
arr2.ptr[len] = cast(int)len; //HERE
arr2 = arr2.ptr[0 .. len + 1];
}
//Check arr2
writeln(arr2);
}
//----
The original line I am concerned about is "HERE": Is this a legal
mutation?
On topic, the actual code in Appender looks like this
//----
//Type of item is "U", with "isImplicitlyConvertible!(U, T)"
_data.arr.ptr[len] = cast(Unqual!T)item;
//----
Worth noting is:
* This will bigtime fail if T has a constructor (should use
emplace).
* Also, is that cast even legal?
If emplace is able to modify the user provided immutable array,
then wouldn't it be better off storing an actual "T[]" (instead
of (Unqual!T)[]): This would avoid any abusive use of casts, and
preserve the qualified type, right?
More information about the Digitalmars-d-learn
mailing list