mirror of
https://github.com/dlang/phobos.git
synced 2025-05-01 15:40:36 +03:00
Implement Phobos side of DIP1014
This commit is contained in:
parent
6010a7ccde
commit
4be9b5f59f
2 changed files with 68 additions and 3 deletions
|
@ -1046,8 +1046,8 @@ to its `.init` value after it is moved into target, otherwise it is
|
|||
left unchanged.
|
||||
|
||||
Preconditions:
|
||||
If source has internal pointers that point to itself, it cannot be moved, and
|
||||
will trigger an assertion failure.
|
||||
If source has internal pointers that point to itself and doesn't define
|
||||
opPostMove, it cannot be moved, and will trigger an assertion failure.
|
||||
|
||||
Params:
|
||||
source = Data to copy.
|
||||
|
@ -1198,6 +1198,24 @@ pure nothrow @safe @nogc unittest
|
|||
assert(s2.a == 2);
|
||||
}
|
||||
|
||||
/// `opPostMove` will be called if defined:
|
||||
pure nothrow @safe @nogc unittest
|
||||
{
|
||||
struct S
|
||||
{
|
||||
int a;
|
||||
void opPostMove(const ref S old)
|
||||
{
|
||||
assert(a == old.a);
|
||||
a++;
|
||||
}
|
||||
}
|
||||
S s1;
|
||||
s1.a = 41;
|
||||
S s2 = move(s1);
|
||||
assert(s2.a == 42);
|
||||
}
|
||||
|
||||
private void trustedMoveImpl(T)(ref T source, ref T target) @trusted
|
||||
{
|
||||
moveImpl(source, target);
|
||||
|
@ -1379,12 +1397,14 @@ void moveEmplace(T)(ref T source, ref T target) @system
|
|||
import core.stdc.string : memcpy, memset;
|
||||
import std.traits : hasAliasing, hasElaborateAssign,
|
||||
hasElaborateCopyConstructor, hasElaborateDestructor,
|
||||
hasElaborateMove,
|
||||
isAssignable, isStaticArray;
|
||||
|
||||
static if (!is(T == class) && hasAliasing!T) if (!__ctfe)
|
||||
{
|
||||
import std.exception : doesPointTo;
|
||||
assert(!doesPointTo(source, source), "Cannot move object with internal pointer.");
|
||||
assert(!(doesPointTo(source, source) && !hasElaborateMove!T),
|
||||
"Cannot move object with internal pointer unless `opPostMove` is defined.");
|
||||
}
|
||||
|
||||
static if (is(T == struct))
|
||||
|
@ -1396,6 +1416,9 @@ void moveEmplace(T)(ref T source, ref T target) @system
|
|||
else
|
||||
target = source;
|
||||
|
||||
static if (hasElaborateMove!T)
|
||||
__move_post_blt(target, source);
|
||||
|
||||
// If the source defines a destructor or a postblit hook, we must obliterate the
|
||||
// object in order to avoid double freeing and undue aliasing
|
||||
static if (hasElaborateDestructor!T || hasElaborateCopyConstructor!T)
|
||||
|
|
42
std/traits.d
42
std/traits.d
|
@ -42,6 +42,7 @@
|
|||
* $(LREF hasElaborateAssign)
|
||||
* $(LREF hasElaborateCopyConstructor)
|
||||
* $(LREF hasElaborateDestructor)
|
||||
* $(LREF hasElaborateMove)
|
||||
* $(LREF hasIndirections)
|
||||
* $(LREF hasMember)
|
||||
* $(LREF hasStaticMember)
|
||||
|
@ -3791,6 +3792,47 @@ template hasElaborateDestructor(S)
|
|||
static assert( hasElaborateDestructor!S7);
|
||||
}
|
||||
|
||||
/**
|
||||
True if `S` or any type embedded directly in the representation of `S`
|
||||
defines elaborate move semantics. Elaborate move semantics are
|
||||
introduced by defining `opPostMove(ref typeof(this))` for a `struct`.
|
||||
|
||||
Classes and unions never have elaborate move semantics.
|
||||
*/
|
||||
template hasElaborateMove(S)
|
||||
{
|
||||
import core.internal.traits : hasElabMove = hasElaborateMove;
|
||||
alias hasElaborateMove = hasElabMove!(S);
|
||||
}
|
||||
|
||||
///
|
||||
@safe unittest
|
||||
{
|
||||
static assert(!hasElaborateMove!int);
|
||||
|
||||
static struct S1 { }
|
||||
static struct S2 { void opPostMove(ref S2) {} }
|
||||
static struct S3 { void opPostMove(inout ref S3) inout {} }
|
||||
static struct S4 { void opPostMove(const ref S4) {} }
|
||||
static struct S5 { void opPostMove(S5) {} }
|
||||
static struct S6 { void opPostMove(int) {} }
|
||||
static struct S7 { S3[1] field; }
|
||||
static struct S8 { S3[] field; }
|
||||
static struct S9 { S3[0] field; }
|
||||
static struct S10 { @disable this(); S3 field; }
|
||||
static assert(!hasElaborateMove!S1);
|
||||
static assert( hasElaborateMove!S2);
|
||||
static assert( hasElaborateMove!S3);
|
||||
static assert( hasElaborateMove!(immutable S3));
|
||||
static assert( hasElaborateMove!S4);
|
||||
static assert(!hasElaborateMove!S5);
|
||||
static assert(!hasElaborateMove!S6);
|
||||
static assert( hasElaborateMove!S7);
|
||||
static assert(!hasElaborateMove!S8);
|
||||
static assert(!hasElaborateMove!S9);
|
||||
static assert( hasElaborateMove!S10);
|
||||
}
|
||||
|
||||
package alias Identity(alias A) = A;
|
||||
|
||||
/**
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue