mirror of
https://github.com/dlang/phobos.git
synced 2025-05-08 03:56:54 +03:00
Merge pull request #2015 from monarchdodra/emplaceQual
Improve emplaceRef for qualified construction
This commit is contained in:
commit
cecd745cef
3 changed files with 191 additions and 175 deletions
|
@ -799,7 +799,7 @@ template reduce(fun...) if (fun.length >= 1)
|
||||||
result = void;
|
result = void;
|
||||||
foreach (i, T; result.Types)
|
foreach (i, T; result.Types)
|
||||||
{
|
{
|
||||||
emplaceRef(result[i], seed);
|
emplaceRef!T(result[i], seed);
|
||||||
}
|
}
|
||||||
r.popFront();
|
r.popFront();
|
||||||
return reduce(result, r);
|
return reduce(result, r);
|
||||||
|
@ -865,7 +865,7 @@ template reduce(fun...) if (fun.length >= 1)
|
||||||
|
|
||||||
foreach (i, T; result.Types)
|
foreach (i, T; result.Types)
|
||||||
{
|
{
|
||||||
emplaceRef(result[i], elem);
|
emplaceRef!T(result[i], elem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1456,7 +1456,7 @@ void uninitializedFill(Range, Value)(Range range, Value filler)
|
||||||
|
|
||||||
// Must construct stuff by the book
|
// Must construct stuff by the book
|
||||||
for (; !range.empty; range.popFront())
|
for (; !range.empty; range.popFront())
|
||||||
emplaceRef(range.front, filler);
|
emplaceRef!T(range.front, filler);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
// Doesn't matter whether fill is initialized or not
|
// Doesn't matter whether fill is initialized or not
|
||||||
|
|
37
std/array.d
37
std/array.d
|
@ -51,7 +51,7 @@ if (isIterable!Range && !isNarrowString!Range && !isInfinite!Range)
|
||||||
size_t i;
|
size_t i;
|
||||||
foreach (e; r)
|
foreach (e; r)
|
||||||
{
|
{
|
||||||
emplaceRef(result[i], e);
|
emplaceRef!E(result[i], e);
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
return cast(E[])result;
|
return cast(E[])result;
|
||||||
|
@ -110,6 +110,12 @@ unittest
|
||||||
static assert(bug12315[0].i == 123456789);
|
static assert(bug12315[0].i == 123456789);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unittest
|
||||||
|
{
|
||||||
|
static struct S{int* p;}
|
||||||
|
auto a = array(immutable(S).init.repeat(5));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Convert a narrow string to an array type that fully supports random access.
|
Convert a narrow string to an array type that fully supports random access.
|
||||||
This is handled as a special case and always returns a $(D dchar[]),
|
This is handled as a special case and always returns a $(D dchar[]),
|
||||||
|
@ -1059,13 +1065,13 @@ void insertInPlace(T, U...)(ref T[] array, size_t pos, U stuff)
|
||||||
{
|
{
|
||||||
static if (is(E : T)) //ditto
|
static if (is(E : T)) //ditto
|
||||||
{
|
{
|
||||||
emplaceRef(tmp[j++], stuff[i]);
|
emplaceRef!T(tmp[j++], stuff[i]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
foreach (v; stuff[i])
|
foreach (v; stuff[i])
|
||||||
{
|
{
|
||||||
emplaceRef(tmp[j++], v);
|
emplaceRef!T(tmp[j++], v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2434,12 +2440,7 @@ struct Appender(A : T[], T)
|
||||||
auto bigDataFun() @trusted nothrow { return _data.arr.ptr[0 .. len + 1];}
|
auto bigDataFun() @trusted nothrow { return _data.arr.ptr[0 .. len + 1];}
|
||||||
auto bigData = bigDataFun();
|
auto bigData = bigDataFun();
|
||||||
|
|
||||||
static if (is(Unqual!T == T))
|
emplaceRef!T(bigData[len], item);
|
||||||
alias uitem = item;
|
|
||||||
else
|
|
||||||
auto ref uitem() @trusted nothrow @property { return cast(Unqual!T)item;}
|
|
||||||
|
|
||||||
emplaceRef(bigData[len], uitem);
|
|
||||||
|
|
||||||
//We do this at the end, in case of exceptions
|
//We do this at the end, in case of exceptions
|
||||||
_data.arr = bigData;
|
_data.arr = bigData;
|
||||||
|
@ -2484,28 +2485,18 @@ struct Appender(A : T[], T)
|
||||||
auto bigDataFun() @trusted nothrow { return _data.arr.ptr[0 .. newlen];}
|
auto bigDataFun() @trusted nothrow { return _data.arr.ptr[0 .. newlen];}
|
||||||
auto bigData = bigDataFun();
|
auto bigData = bigDataFun();
|
||||||
|
|
||||||
enum mustEmplace = is(typeof(bigData[0].opAssign(cast(Unqual!T)items.front))) ||
|
alias UT = Unqual!T;
|
||||||
!is(typeof(bigData[0] = cast(Unqual!T)items.front));
|
|
||||||
|
|
||||||
static if (is(typeof(_data.arr[] = items[])) && !mustEmplace)
|
static if (is(typeof(_data.arr[] = items[])) &&
|
||||||
|
!hasElaborateAssign!(Unqual!T) && isAssignable!(UT, ElementEncodingType!Range))
|
||||||
{
|
{
|
||||||
//pragma(msg, T.stringof); pragma(msg, Range.stringof);
|
|
||||||
bigData[len .. newlen] = items[];
|
bigData[len .. newlen] = items[];
|
||||||
}
|
}
|
||||||
else static if (is(Unqual!T == ElementType!Range))
|
|
||||||
{
|
|
||||||
foreach (ref it ; bigData[len .. newlen])
|
|
||||||
{
|
|
||||||
emplaceRef(it, items.front);
|
|
||||||
items.popFront();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
static auto ref getUItem(U)(U item) @trusted {return cast(Unqual!T)item;}
|
|
||||||
foreach (ref it ; bigData[len .. newlen])
|
foreach (ref it ; bigData[len .. newlen])
|
||||||
{
|
{
|
||||||
emplaceRef(it, getUItem(items.front));
|
emplaceRef!T(it, items.front);
|
||||||
items.popFront();
|
items.popFront();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
323
std/conv.d
323
std/conv.d
|
@ -3845,170 +3845,169 @@ 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
|
This makes it easier to use, easier to be safe, and faster in a non-inline
|
||||||
build.
|
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.
|
||||||
+/
|
+/
|
||||||
package ref T emplaceRef(T)(ref T chunk)
|
package template emplaceRef(T)
|
||||||
{
|
{
|
||||||
static assert (is(T* : void*),
|
alias UT = Unqual!T;
|
||||||
format("Cannot emplace a %s because it is qualified.", T.stringof));
|
|
||||||
|
|
||||||
static assert (is(typeof({static T i;})),
|
ref UT emplaceRef()(ref UT chunk)
|
||||||
format("Cannot emplace a %1$s because %1$s.this() is annotated with @disable.", T.stringof));
|
|
||||||
|
|
||||||
return emplaceInitializer(chunk);
|
|
||||||
}
|
|
||||||
// ditto
|
|
||||||
package ref T emplaceRef(T, Args...)(ref T chunk, auto ref Args args)
|
|
||||||
if (!is(T == struct) && Args.length == 1)
|
|
||||||
{
|
|
||||||
alias Arg = Args[0];
|
|
||||||
alias arg = args[0];
|
|
||||||
|
|
||||||
static assert (is(T* : void*),
|
|
||||||
format("Cannot emplace a %s because it is qualified.", T.stringof));
|
|
||||||
|
|
||||||
static assert(is(typeof({T t = args[0];})),
|
|
||||||
format("%s cannot be emplaced from a %s.", T.stringof, Arg.stringof));
|
|
||||||
|
|
||||||
static if (isStaticArray!T)
|
|
||||||
{
|
{
|
||||||
alias UArg = Unqual!Arg;
|
static assert (is(typeof({static T i;})),
|
||||||
alias E = typeof(chunk.ptr[0]);
|
format("Cannot emplace a %1$s because %1$s.this() is annotated with @disable.", T.stringof));
|
||||||
enum N = T.length;
|
|
||||||
|
return emplaceInitializer(chunk);
|
||||||
|
}
|
||||||
|
|
||||||
static if (is(Arg : T))
|
static if (!is(T == struct))
|
||||||
|
ref UT emplaceRef(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));
|
||||||
|
|
||||||
|
static if (isStaticArray!T)
|
||||||
{
|
{
|
||||||
//Matching static array
|
alias UArg = Unqual!Arg;
|
||||||
static if (!hasElaborateAssign!T && isAssignable!(T, Arg))
|
alias E = ElementEncodingType!(typeof(T.init[]));
|
||||||
chunk = arg;
|
alias UE = Unqual!E;
|
||||||
else static if (is(UArg == T))
|
enum N = T.length;
|
||||||
|
|
||||||
|
static if (is(Arg : T))
|
||||||
{
|
{
|
||||||
memcpy(&chunk, &arg, T.sizeof);
|
//Matching static array
|
||||||
static if (hasElaborateCopyConstructor!T)
|
static if (!hasElaborateAssign!UT && isAssignable!(UT, Arg))
|
||||||
typeid(T).postblit(cast(void*)&chunk);
|
chunk = arg;
|
||||||
|
else static if (is(UArg == UT))
|
||||||
|
{
|
||||||
|
memcpy(&chunk, &arg, T.sizeof);
|
||||||
|
static if (hasElaborateCopyConstructor!T)
|
||||||
|
typeid(T).postblit(cast(void*)&chunk);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
.emplaceRef!T(chunk, cast(T)arg);
|
||||||
|
}
|
||||||
|
else static if (is(Arg : E[]))
|
||||||
|
{
|
||||||
|
//Matching dynamic array
|
||||||
|
static if (!hasElaborateAssign!UT && is(typeof(chunk[] = arg[])))
|
||||||
|
chunk[] = arg[];
|
||||||
|
else static if (is(Unqual!(ElementEncodingType!Arg) == UE))
|
||||||
|
{
|
||||||
|
assert(N == chunk.length, "Array length missmatch in emplace");
|
||||||
|
memcpy(cast(void*)&chunk, arg.ptr, T.sizeof);
|
||||||
|
static if (hasElaborateCopyConstructor!T)
|
||||||
|
typeid(T).postblit(cast(void*)&chunk);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
.emplaceRef!T(chunk, cast(E[])arg);
|
||||||
|
}
|
||||||
|
else static if (is(Arg : E))
|
||||||
|
{
|
||||||
|
//Case matching single element to array.
|
||||||
|
static if (!hasElaborateAssign!UT && is(typeof(chunk[] = arg)))
|
||||||
|
chunk[] = arg;
|
||||||
|
else static if (is(UArg == Unqual!E))
|
||||||
|
{
|
||||||
|
//Note: We copy everything, and then postblit just once.
|
||||||
|
//This is as exception safe as what druntime can provide us.
|
||||||
|
foreach(i; 0 .. N)
|
||||||
|
memcpy(cast(void*)&(chunk[i]), &arg, E.sizeof);
|
||||||
|
static if (hasElaborateCopyConstructor!T)
|
||||||
|
typeid(T).postblit(cast(void*)&chunk);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
//Alias this. Coerce.
|
||||||
|
.emplaceRef!T(chunk, cast(E)arg);
|
||||||
|
}
|
||||||
|
else static if (is(typeof(.emplaceRef!E(chunk[0], arg))))
|
||||||
|
{
|
||||||
|
//Final case for everything else:
|
||||||
|
//Types that don't match (int to uint[2])
|
||||||
|
//Recursion for multidimensions
|
||||||
|
static if (!hasElaborateAssign!UT && is(typeof(chunk[] = arg)))
|
||||||
|
chunk[] = arg;
|
||||||
|
else
|
||||||
|
foreach(i; 0 .. N)
|
||||||
|
.emplaceRef!E(chunk[i], arg);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
emplaceRef(chunk, cast(T)arg);
|
static assert(0, format("Sorry, this implementation doesn't know how to emplace a %s with a %s", T.stringof, Arg.stringof));
|
||||||
}
|
|
||||||
else static if (is(Arg : E[]))
|
return chunk;
|
||||||
{
|
|
||||||
//Matching dynamic array
|
|
||||||
static if (!hasElaborateAssign!T && is(typeof(chunk[] = arg[])))
|
|
||||||
chunk[] = arg[];
|
|
||||||
else static if (is(UArg == E[]))
|
|
||||||
{
|
|
||||||
assert(N == chunk.length, "Array length missmatch in emplace");
|
|
||||||
memcpy(cast(void*)&chunk, arg.ptr, T.sizeof);
|
|
||||||
static if (hasElaborateCopyConstructor!T)
|
|
||||||
typeid(T).postblit(cast(void*)&chunk);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
emplaceRef(chunk, cast(E[])arg);
|
|
||||||
}
|
|
||||||
else static if (is(Arg : E))
|
|
||||||
{
|
|
||||||
//Case matching single element to array.
|
|
||||||
static if (!hasElaborateAssign!T && is(typeof(chunk[] = arg)))
|
|
||||||
chunk[] = arg;
|
|
||||||
else static if (is(UArg == E))
|
|
||||||
{
|
|
||||||
//Note: We copy everything, and then postblit just once.
|
|
||||||
//This is as exception safe as what druntime can provide us.
|
|
||||||
foreach(i; 0 .. N)
|
|
||||||
memcpy(cast(void*)&(chunk[i]), &arg, E.sizeof);
|
|
||||||
static if (hasElaborateCopyConstructor!T)
|
|
||||||
typeid(T).postblit(cast(void*)&chunk);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
//Alias this. Coerce.
|
|
||||||
emplaceRef(chunk, cast(E)arg);
|
|
||||||
}
|
|
||||||
else static if (is(typeof(emplaceRef(chunk[0], arg))))
|
|
||||||
{
|
|
||||||
//Final case for everything else:
|
|
||||||
//Types that don't match (int to uint[2])
|
|
||||||
//Recursion for multidimensions
|
|
||||||
static if (!hasElaborateAssign!T && is(typeof(chunk[] = arg)))
|
|
||||||
chunk[] = arg;
|
|
||||||
else
|
|
||||||
foreach(i; 0 .. N)
|
|
||||||
emplaceRef(chunk[i], arg);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
static assert(0, format("Sorry, this implementation doesn't know how to emplace a %s with a %s", T.stringof, Arg.stringof));
|
|
||||||
|
|
||||||
return chunk;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
chunk = arg;
|
|
||||||
return chunk;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// ditto
|
|
||||||
package ref T emplaceRef(T, Args...)(ref T chunk, auto ref Args args)
|
|
||||||
if (is(T == struct))
|
|
||||||
{
|
|
||||||
static assert (is(T* : void*),
|
|
||||||
format("Cannot emplace a %s because it is qualified.", T.stringof));
|
|
||||||
|
|
||||||
static if (Args.length == 1 && is(Args[0] : T) &&
|
|
||||||
is (typeof({T t = args[0];})) //Check for legal postblit
|
|
||||||
)
|
|
||||||
{
|
|
||||||
static if (is(T == Unqual!(Args[0])))
|
|
||||||
{
|
{
|
||||||
//Types match exactly: we postblit
|
chunk = arg;
|
||||||
static if (!hasElaborateAssign!T && isAssignable!T)
|
return chunk;
|
||||||
chunk = args[0];
|
}
|
||||||
else
|
}
|
||||||
|
// ditto
|
||||||
|
static if (is(T == struct))
|
||||||
|
ref UT emplaceRef(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
|
||||||
|
)
|
||||||
|
{
|
||||||
|
static if (is(Unqual!T == Unqual!(Args[0])))
|
||||||
{
|
{
|
||||||
memcpy(&chunk, &args[0], T.sizeof);
|
//Types match exactly: we postblit
|
||||||
static if (hasElaborateCopyConstructor!T)
|
static if (!hasElaborateAssign!UT && isAssignable!(UT, T))
|
||||||
typeid(T).postblit(&chunk);
|
chunk = args[0];
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memcpy(&chunk, &args[0], T.sizeof);
|
||||||
|
static if (hasElaborateCopyConstructor!T)
|
||||||
|
typeid(T).postblit(&chunk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
//Alias this. Coerce to type T.
|
||||||
|
.emplaceRef!T(chunk, cast(T)args[0]);
|
||||||
|
}
|
||||||
|
else static if (is(typeof(chunk.__ctor(args))))
|
||||||
|
{
|
||||||
|
// T defines a genuine constructor accepting args
|
||||||
|
// Go the classic route: write .init first, then call ctor
|
||||||
|
emplaceInitializer(chunk);
|
||||||
|
chunk.__ctor(args);
|
||||||
|
}
|
||||||
|
else static if (is(typeof(T.opCall(args))))
|
||||||
|
{
|
||||||
|
//Can be built calling opCall
|
||||||
|
emplaceOpCaller(chunk, args); //emplaceOpCaller is deprecated
|
||||||
|
}
|
||||||
|
else static if (is(typeof(T(args))))
|
||||||
|
{
|
||||||
|
// Struct without constructor that has one matching field for
|
||||||
|
// each argument. Individually emplace each field
|
||||||
|
emplaceInitializer(chunk);
|
||||||
|
foreach (i, ref field; chunk.tupleof[0 .. Args.length])
|
||||||
|
{
|
||||||
|
alias Field = typeof(field);
|
||||||
|
alias UField = Unqual!Field;
|
||||||
|
static if (is(Field == UField))
|
||||||
|
.emplaceRef!Field(field, args[i]);
|
||||||
|
else
|
||||||
|
.emplaceRef!Field(*cast(Unqual!Field*)&field, args[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
//Alias this. Coerce to type T.
|
|
||||||
emplaceRef(chunk, cast(T)args[0]);
|
|
||||||
}
|
|
||||||
else static if (is(typeof(chunk.__ctor(args))))
|
|
||||||
{
|
|
||||||
// T defines a genuine constructor accepting args
|
|
||||||
// Go the classic route: write .init first, then call ctor
|
|
||||||
emplaceInitializer(chunk);
|
|
||||||
chunk.__ctor(args);
|
|
||||||
}
|
|
||||||
else static if (is(typeof(T.opCall(args))))
|
|
||||||
{
|
|
||||||
//Can be built calling opCall
|
|
||||||
emplaceOpCaller(chunk, args); //emplaceOpCaller is deprecated
|
|
||||||
}
|
|
||||||
else static if (is(typeof(T(args))))
|
|
||||||
{
|
|
||||||
// Struct without constructor that has one matching field for
|
|
||||||
// each argument. Individually emplace each field
|
|
||||||
emplaceInitializer(chunk);
|
|
||||||
foreach (i, ref field; chunk.tupleof[0 .. Args.length])
|
|
||||||
{
|
{
|
||||||
alias Field = typeof(field);
|
//We can't emplace. Try to diagnose a disabled postblit.
|
||||||
static if (is(Field == Unqual!Field))
|
static assert(!(Args.length == 1 && is(Args[0] : T)),
|
||||||
emplaceRef(field, args[i]);
|
format("Cannot emplace a %1$s because %1$s.this(this) is annotated with @disable.", T.stringof));
|
||||||
else
|
|
||||||
emplaceRef(*cast(Unqual!Field*)&field, args[i]);
|
//We can't emplace.
|
||||||
|
static assert(false,
|
||||||
|
format("%s cannot be emplaced from %s.", T.stringof, Args[].stringof));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return chunk;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
//We can't emplace. Try to diagnose a disabled postblit.
|
|
||||||
static assert(!(Args.length == 1 && is(Args[0] : T)),
|
|
||||||
format("Cannot emplace a %1$s because %1$s.this(this) is annotated with @disable.", T.stringof));
|
|
||||||
|
|
||||||
//We can't emplace.
|
|
||||||
static assert(false,
|
|
||||||
format("%s cannot be emplaced from %s.", T.stringof, Args[].stringof));
|
|
||||||
}
|
|
||||||
|
|
||||||
return chunk;
|
|
||||||
}
|
}
|
||||||
//emplace helper functions
|
//emplace helper functions
|
||||||
private ref T emplaceInitializer(T)(ref T chunk) @trusted pure nothrow
|
private ref T emplaceInitializer(T)(ref T chunk) @trusted pure nothrow
|
||||||
|
@ -4027,7 +4026,7 @@ ref T emplaceOpCaller(T, Args...)(ref T chunk, auto ref Args args)
|
||||||
{
|
{
|
||||||
static assert (is(typeof({T t = T.opCall(args);})),
|
static assert (is(typeof({T t = T.opCall(args);})),
|
||||||
format("%s.opCall does not return adequate data for construction.", T.stringof));
|
format("%s.opCall does not return adequate data for construction.", T.stringof));
|
||||||
return emplaceRef(chunk, chunk.opCall(args));
|
return emplaceRef!T(chunk, chunk.opCall(args));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -4042,7 +4041,7 @@ as $(D chunk)).
|
||||||
*/
|
*/
|
||||||
T* emplace(T)(T* chunk) @safe nothrow pure
|
T* emplace(T)(T* chunk) @safe nothrow pure
|
||||||
{
|
{
|
||||||
emplaceRef(*chunk);
|
emplaceRef!T(*chunk);
|
||||||
return chunk;
|
return chunk;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4060,14 +4059,14 @@ as $(D chunk)).
|
||||||
T* emplace(T, Args...)(T* chunk, auto ref Args args)
|
T* emplace(T, Args...)(T* chunk, auto ref Args args)
|
||||||
if (!is(T == struct) && Args.length == 1)
|
if (!is(T == struct) && Args.length == 1)
|
||||||
{
|
{
|
||||||
emplaceRef(*chunk, args);
|
emplaceRef!T(*chunk, args);
|
||||||
return chunk;
|
return chunk;
|
||||||
}
|
}
|
||||||
/// ditto
|
/// ditto
|
||||||
T* emplace(T, Args...)(T* chunk, auto ref Args args)
|
T* emplace(T, Args...)(T* chunk, auto ref Args args)
|
||||||
if (is(T == struct))
|
if (is(T == struct))
|
||||||
{
|
{
|
||||||
emplaceRef(*chunk, args);
|
emplaceRef!T(*chunk, args);
|
||||||
return chunk;
|
return chunk;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4858,6 +4857,32 @@ unittest
|
||||||
emplace(&sss, s);
|
emplace(&sss, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unittest //Constness
|
||||||
|
{
|
||||||
|
import std.stdio;
|
||||||
|
|
||||||
|
int a = void;
|
||||||
|
emplaceRef!(const int)(a, 5);
|
||||||
|
|
||||||
|
immutable i = 5;
|
||||||
|
const(int)* p = void;
|
||||||
|
emplaceRef!(const int*)(p, &i);
|
||||||
|
|
||||||
|
struct S
|
||||||
|
{
|
||||||
|
int* p;
|
||||||
|
}
|
||||||
|
alias IS = immutable(S);
|
||||||
|
S s = void;
|
||||||
|
emplaceRef!IS(s, IS());
|
||||||
|
S[2] ss = void;
|
||||||
|
emplaceRef!(IS[2])(ss, IS());
|
||||||
|
|
||||||
|
IS[2] iss = IS.init;
|
||||||
|
emplaceRef!(IS[2])(ss, iss);
|
||||||
|
emplaceRef!(IS[2])(ss, iss[]);
|
||||||
|
}
|
||||||
|
|
||||||
private void testEmplaceChunk(void[] chunk, size_t typeSize, size_t typeAlignment, string typeName)
|
private void testEmplaceChunk(void[] chunk, size_t typeSize, size_t typeAlignment, string typeName)
|
||||||
{
|
{
|
||||||
enforceEx!ConvException(chunk.length >= typeSize,
|
enforceEx!ConvException(chunk.length >= typeSize,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue