diff --git a/changelog/aa-init.dd b/changelog/aa-init.dd new file mode 100644 index 0000000000..c736ab2baf --- /dev/null +++ b/changelog/aa-init.dd @@ -0,0 +1,18 @@ +Added `initialize` function for associative arrays + +This function allocates memory for an empty associative array (AA). It +is useful to avoid copying a null AA reference. Then +when AA elements are added through the original reference, the copied +reference will still point to the same AA: +--- +int[int] aa; +auto b = aa; +assert(b is null); +aa.initialize; +assert(aa !is null); +auto c = aa; + +aa[4] = 4; +assert(b != aa); +assert(c is aa); +--- diff --git a/src/object.d b/src/object.d index 4bbfe3bc1f..96bc4dd043 100644 --- a/src/object.d +++ b/src/object.d @@ -3024,6 +3024,7 @@ extern (C) inout(void)[] _aaKeys(inout void* p, in size_t keysize, const TypeInfo tiKeyArray) pure nothrow; void* _aaRehash(void** pp, in TypeInfo keyti) pure nothrow; void _aaClear(void* p) pure nothrow; + void _aaInitialize(void* p, const TypeInfo_AssociativeArray ti); // alias _dg_t = extern(D) int delegate(void*); // int _aaApply(void* aa, size_t keysize, _dg_t dg); @@ -3057,10 +3058,47 @@ void* aaLiteral(Key, Value)(Key[] keys, Value[] values) @trusted pure alias AssociativeArray(Key, Value) = Value[Key]; +/*********************************** + * Allocate memory for an empty associative array. + * This is useful to avoid copying a null reference when each reference + * should point to the same associative array data. + * Without using this function, an associative array is initialized only + * when the first element is added. + * Params: + * aa = The associative array. + * See_Also: $(LREF clear) + */ +void initialize(T : Value[Key], Value, Key)(ref T aa) @trusted +{ + _aaInitialize(cast(void*) &aa, typeid(T)); +} + +/// +@safe unittest +{ + int[int] aa; + auto b = aa; + assert(b is null); + aa.initialize; + assert(aa !is null); + auto c = aa; + + aa[4] = 4; + assert(b != aa); + assert(c is aa); +} + +/* ditto */ +void initialize(T : Value[Key], Value, Key)(T* aa) @safe +{ + _aaInitialize(cast(void*) aa, typeid(T)); +} + /*********************************** * Removes all remaining keys and values from an associative array. * Params: * aa = The associative array. + * See_Also: $(LREF initialize) */ void clear(T : Value[Key], Value, Key)(T aa) { diff --git a/src/rt/aaA.d b/src/rt/aaA.d index 08dd932df9..5b221b27cb 100644 --- a/src/rt/aaA.d +++ b/src/rt/aaA.d @@ -640,6 +640,12 @@ extern (C) void _aaClear(AA aa) pure nothrow } } +/// Allocate new AA implementation. +extern (C) void _aaInitialize(AA* paa, const TypeInfo_AssociativeArray ti) +{ + paa.impl = new Impl(ti); +} + /// Rehash AA extern (C) void* _aaRehash(AA* paa, in TypeInfo keyti) pure nothrow {