Skip to content

Commit

Permalink
Merge pull request #2160 from monarchdodra/emplaceRef
Browse files Browse the repository at this point in the history
Make emplaceRef parameter optional
  • Loading branch information
DmitryOlshansky committed Jul 20, 2014
2 parents 5d7c4c0 + 4b16412 commit bc270d2
Showing 1 changed file with 41 additions and 19 deletions.
60 changes: 41 additions & 19 deletions std/conv.d
Expand Up @@ -3819,15 +3819,28 @@ emplace, but takes its argument by ref (as opposed to "by pointer").
This makes it easier to use, easier to be safe, and faster in a non-inline
build.
Furthermore, emplaceRef takes a type paremeter, which specifies the type we
want to build. This helps to build qualified objects on mutable buffer,
without breaking the type system with unsafe casts.
Furthermore, emplaceRef optionally takes a type paremeter, which specifies
the type we want to build. This helps to build qualified objects on mutable
buffer, without breaking the type system with unsafe casts.
+/
package template emplaceRef(T)
package ref UT emplaceRef(UT, Args...)(ref UT chunk, auto ref Args args)
if (is(UT == Unqual!UT))
{
return emplaceImpl!UT(chunk, args);
}
// ditto
package ref UT emplaceRef(T, UT, Args...)(ref UT chunk, auto ref Args args)
if (is(UT == Unqual!T) && !is(T == UT))
{
return emplaceImpl!T(chunk, args);
}


private template emplaceImpl(T)
{
alias UT = Unqual!T;

ref UT emplaceRef()(ref UT chunk)
ref UT emplaceImpl()(ref UT chunk)
{
static assert (is(typeof({static T i;})),
format("Cannot emplace a %1$s because %1$s.this() is annotated with @disable.", T.stringof));
Expand All @@ -3836,7 +3849,7 @@ package template emplaceRef(T)
}

static if (!is(T == struct))
ref UT emplaceRef(Arg)(ref UT chunk, auto ref Arg arg)
ref UT emplaceImpl(Arg)(ref UT chunk, auto ref Arg arg)
{
static assert(is(typeof({T t = arg;})),
format("%s cannot be emplaced from a %s.", T.stringof, Arg.stringof));
Expand All @@ -3860,7 +3873,7 @@ package template emplaceRef(T)
typeid(T).postblit(cast(void*)&chunk);
}
else
.emplaceRef!T(chunk, cast(T)arg);
.emplaceImpl!T(chunk, cast(T)arg);
}
else static if (is(Arg : E[]))
{
Expand All @@ -3875,7 +3888,7 @@ package template emplaceRef(T)
typeid(T).postblit(cast(void*)&chunk);
}
else
.emplaceRef!T(chunk, cast(E[])arg);
.emplaceImpl!T(chunk, cast(E[])arg);
}
else static if (is(Arg : E))
{
Expand All @@ -3893,9 +3906,9 @@ package template emplaceRef(T)
}
else
//Alias this. Coerce.
.emplaceRef!T(chunk, cast(E)arg);
.emplaceImpl!T(chunk, cast(E)arg);
}
else static if (is(typeof(.emplaceRef!E(chunk[0], arg))))
else static if (is(typeof(.emplaceImpl!E(chunk[0], arg))))
{
//Final case for everything else:
//Types that don't match (int to uint[2])
Expand All @@ -3904,7 +3917,7 @@ package template emplaceRef(T)
chunk[] = arg;
else
foreach(i; 0 .. N)
.emplaceRef!E(chunk[i], arg);
.emplaceImpl!E(chunk[i], arg);
}
else
static assert(0, format("Sorry, this implementation doesn't know how to emplace a %s with a %s", T.stringof, Arg.stringof));
Expand All @@ -3919,7 +3932,7 @@ package template emplaceRef(T)
}
// ditto
static if (is(T == struct))
ref UT emplaceRef(Args...)(ref UT chunk, auto ref Args args)
ref UT emplaceImpl(Args...)(ref UT chunk, auto ref Args args)
{
static if (Args.length == 1 && is(Args[0] : T) &&
is (typeof({T t = args[0];})) //Check for legal postblit
Expand All @@ -3939,7 +3952,7 @@ package template emplaceRef(T)
}
else
//Alias this. Coerce to type T.
.emplaceRef!T(chunk, cast(T)args[0]);
.emplaceImpl!T(chunk, cast(T)args[0]);
}
else static if (is(typeof(chunk.__ctor(args))))
{
Expand All @@ -3963,9 +3976,9 @@ package template emplaceRef(T)
alias Field = typeof(field);
alias UField = Unqual!Field;
static if (is(Field == UField))
.emplaceRef!Field(field, args[i]);
.emplaceImpl!Field(field, args[i]);
else
.emplaceRef!Field(*cast(Unqual!Field*)&field, args[i]);
.emplaceImpl!Field(*cast(Unqual!Field*)&field, args[i]);
}
}
else
Expand Down Expand Up @@ -3999,7 +4012,7 @@ ref T emplaceOpCaller(T, Args...)(ref T chunk, auto ref Args args)
{
static assert (is(typeof({T t = T.opCall(args);})),
format("%s.opCall does not return adequate data for construction.", T.stringof));
return emplaceRef!T(chunk, chunk.opCall(args));
return emplaceImpl!T(chunk, chunk.opCall(args));
}


Expand All @@ -4014,7 +4027,7 @@ as $(D chunk)).
*/
T* emplace(T)(T* chunk) @safe pure nothrow
{
emplaceRef!T(*chunk);
emplaceImpl!T(*chunk);
return chunk;
}

Expand All @@ -4032,14 +4045,14 @@ as $(D chunk)).
T* emplace(T, Args...)(T* chunk, auto ref Args args)
if (!is(T == struct) && Args.length == 1)
{
emplaceRef!T(*chunk, args);
emplaceImpl!T(*chunk, args);
return chunk;
}
/// ditto
T* emplace(T, Args...)(T* chunk, auto ref Args args)
if (is(T == struct))
{
emplaceRef!T(*chunk, args);
emplaceImpl!T(*chunk, args);
return chunk;
}

Expand Down Expand Up @@ -4854,6 +4867,15 @@ unittest //Constness
emplaceRef!(IS[2])(ss, iss[]);
}

unittest
{
int i;
emplaceRef(i);
emplaceRef!int(i);
emplaceRef(i, 5);
emplaceRef!int(i, 5);
}

private void testEmplaceChunk(void[] chunk, size_t typeSize, size_t typeAlignment, string typeName)
{
enforceEx!ConvException(chunk.length >= typeSize,
Expand Down

0 comments on commit bc270d2

Please sign in to comment.