algorithm.mutation.destroyAll: New

Fix #71.
This commit is contained in:
Eugen Wissner 2018-10-29 11:14:33 +01:00
parent 64ceb0330c
commit 1e46109e50
3 changed files with 53 additions and 21 deletions

View File

@ -561,3 +561,49 @@ if (isInputRange!Range && hasLvalueElements!Range)
NonCopyable[] nonCopyable; NonCopyable[] nonCopyable;
initializeAll(nonCopyable); initializeAll(nonCopyable);
} }
/**
* Destroys all elements in the $(D_PARAM range).
*
* This function has effect only if the element type of $(D_PARAM Range) has
* an elaborate destructor, i.e. it is a $(D_PSYMBOL struct) with an explicit
* or generated by the compiler destructor.
*
* Params:
* Range = Input range type.
* range = Input range.
*/
void destroyAll(Range)(Range range)
if (isInputRange!Range && hasLvalueElements!Range)
{
static if (hasElaborateDestructor!(ElementType!Range))
{
foreach (ref e; range)
{
destroy(e);
}
}
}
///
@nogc nothrow pure @trusted unittest
{
static struct WithDtor
{
private size_t* counter;
~this() @nogc nothrow pure
{
if (this.counter !is null)
{
++(*this.counter);
}
}
}
size_t counter;
WithDtor[2] withDtor = [WithDtor(&counter), WithDtor(&counter)];
destroyAll(withDtor[]);
assert(counter == 2);
}

View File

@ -414,27 +414,19 @@ struct Array(T)
*/ */
@property void length(size_t len) @trusted @property void length(size_t len) @trusted
{ {
if (len == length) if (len > length)
{
return;
}
else if (len > length)
{ {
reserve(len); reserve(len);
initializeAll(this.data[length_ .. len]); initializeAll(this.data[length_ .. len]);
} }
else else
{ {
static if (hasElaborateDestructor!T) destroyAll(this.data[len .. this.length_]);
{ }
const T* end = this.data + length_ - 1; if (len != length)
for (T* e = this.data + len; e != end; ++e) {
{ length_ = len;
destroy(*e);
}
}
} }
length_ = len;
} }
/// ///

View File

@ -341,13 +341,7 @@ if (isPolymorphicType!T)
package(tanya) void[] finalize(T)(ref T[] p) package(tanya) void[] finalize(T)(ref T[] p)
{ {
static if (hasElaborateDestructor!(typeof(p[0]))) destroyAll(p);
{
foreach (ref e; p)
{
destroy(e);
}
}
return p; return p;
} }