Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions std/algorithm.d
Original file line number Diff line number Diff line change
Expand Up @@ -794,7 +794,7 @@ template reduce(fun...) if (fun.length >= 1)
result = void;
foreach (i, T; result.Types)
{
emplace(&result[i], seed);
autoEmplace(result[i], seed);
}
r.popFront();
return reduce(result, r);
Expand Down Expand Up @@ -856,7 +856,7 @@ template reduce(fun...) if (fun.length >= 1)

foreach (i, T; result.Types)
{
emplace(&result[i], elem);
autoEmplace(result[i], elem);
}
}
}
Expand Down Expand Up @@ -1186,7 +1186,7 @@ void uninitializedFill(Range, Value)(Range range, Value filler)
{
// Must construct stuff by the book
for (; !range.empty; range.popFront())
emplace(addressOf(range.front), filler);
autoEmplace(range.front, filler);
}
else
// Doesn't matter whether fill is initialized or not
Expand Down
16 changes: 6 additions & 10 deletions std/array.d
Original file line number Diff line number Diff line change
Expand Up @@ -30,22 +30,19 @@ if (isIterable!Range && !isNarrowString!Range && !isInfinite!Range)
alias ForeachType!Range E;
static if (hasLength!Range)
{
if(r.length == 0) return null;
immutable len = r.length;
if(len == 0) return null;

static auto trustedAllocateArray(size_t n) @trusted nothrow
{
return uninitializedArray!(Unqual!E[])(n);
}
auto result = trustedAllocateArray(r.length);
auto result = trustedAllocateArray(len);

size_t i;
static auto trustedGetAddr(T)(ref T t) @trusted nothrow pure
{
return &t;
}
foreach (e; r)
{
emplace(trustedGetAddr(result[i]), e);
autoEmplace(result[i], e);
++i;
}
return cast(E[])result;
Expand Down Expand Up @@ -913,17 +910,16 @@ void insertInPlace(T, U...)(ref T[] array, size_t pos, U stuff)
}
array.length += to_insert;
copyBackwards(array[pos..oldLen], array[pos+to_insert..$]);
auto ptr = array.ptr + pos;
foreach (i, E; U)
{
static if (is(E : T)) //ditto
{
emplace(ptr++, stuff[i]);
autoEmplace(array[pos++], stuff[i]);
}
else
{
foreach (v; stuff[i])
emplace(ptr++, v);
autoEmplace(array[pos++], v);
}
}
}
Expand Down
49 changes: 49 additions & 0 deletions std/conv.d
Original file line number Diff line number Diff line change
Expand Up @@ -4833,6 +4833,55 @@ unittest
assert(equal(map!(to!int)(["42", "34", "345"]), [42, 34, 345]));
}

/+
package helper: This function is functionally equivalent to the normal
emplace. However, it only calls the actual emplace if really necessary.
It's dedicated to improving both code readability and performance.
This function is mostly a workaround for DMD's bad inliner.

Doing it as a dedicated function helps reduce error-prone boilerplate
code in caller function. Indeed: While the normal emplace will still
correctly call '=' when needed, it takes an argument by pointer. DMD
seems to have a lot of trouble making the inline assignment when there
is an un-necessary indirection.

eg:
----
int i;
emplace(&i, 5);
vs
autoEmplace(i, 5);
----

Using $(D emplace) over raw assignement or $(D autoEmplace) for trivial
types in a tight loop $(I can) result in a $(I catastrophic) performance
penalty.
+/
package void autoEmplace(T, Args...)(ref T chunk, auto ref Args args)
{
static if (Args.length == 0 && isAssignable!(T) && !hasElaborateAssign!T)
chunk = T.init;
else static if (Args.length == 1 && isAssignable!(T, Args[0]) && !hasElaborateAssign!T)
chunk = args[0];
else
emplace(&chunk, args);
}

unittest
{
int i;
autoEmplace(i);
autoEmplace(i, 5);

static struct S
{
void opAssign(S);
}
S s;
autoEmplace(s);
autoEmplace(s, S.init);
}

// Undocumented for the time being
void toTextRange(T, W)(T value, W writer)
if (isIntegral!T && isOutputRange!(W, char))
Expand Down
2 changes: 1 addition & 1 deletion std/functional.d
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,7 @@ template adjoin(F...) if (F.length)
Tuple!(Head, typeof(.adjoin!(F[1..$])(a)).Types) result = void;
foreach (i, Unused; result.Types)
{
emplace(&result[i], F[i](a));
autoEmplace(result[i], F[i](a));
}
return result;
}
Expand Down
2 changes: 1 addition & 1 deletion std/typecons.d
Original file line number Diff line number Diff line change
Expand Up @@ -3522,7 +3522,7 @@ if (!is(T == class))
_store = cast(Impl*) enforce(malloc(Impl.sizeof));
static if (hasIndirections!T)
GC.addRange(&_store._payload, T.sizeof);
emplace(&_store._payload, args);
autoEmplace(_store._payload, args);
_store._count = 1;
}

Expand Down