Skip to content

Commit

Permalink
fix swap to check full mutability
Browse files Browse the repository at this point in the history
  • Loading branch information
monarchdodra committed Oct 22, 2013
1 parent bfbf0d3 commit 7e2e705
Showing 1 changed file with 41 additions and 1 deletion.
42 changes: 41 additions & 1 deletion std/algorithm.d
Expand Up @@ -1945,7 +1945,7 @@ See_Also:
$(XREF exception, pointsTo)
*/
void swap(T)(ref T lhs, ref T rhs) @trusted pure nothrow
if (isMutable!T && !is(typeof(T.init.proxySwap(T.init))))
if (allMutableFields!T && !is(typeof(T.init.proxySwap(T.init))))
{
static if (!isAssignable!T || hasElaborateAssign!T)
{
Expand Down Expand Up @@ -1992,6 +1992,36 @@ void swap(T)(T lhs, T rhs) if (is(typeof(T.init.proxySwap(T.init))))
lhs.proxySwap(rhs);
}

/+
Trait like isMutable. It also verifies that the fields inside a value
type aggregate are also mutable.
A "value type aggregate" is a struct or an union, but not a class nor
an interface.
+/
private template allMutableFields(T)
{
alias OT = OriginalType!T;
static if (is(OT == struct) || is(OT == union))
enum allMutableFields = isMutable!OT && allSatisfy!(.allMutableFields, FieldTypeTuple!OT);
else
enum allMutableFields = isMutable!OT;
}

unittest
{
static assert( allMutableFields!int);
static assert(!allMutableFields!(const int));

class C{const int i;}
static assert( allMutableFields!C);

struct S1{int i;}
struct S2{const int i;}
static assert( allMutableFields!S1);
static assert(!allMutableFields!S2);
}

unittest
{
debug(std_algorithm) scope(success)
Expand Down Expand Up @@ -2076,6 +2106,16 @@ unittest
assert(s2.i == 1);
}

unittest
{
struct S
{
const int i;
}
S s;
static assert(!__traits(compiles, swap(s, s)));
}

void swapFront(R1, R2)(R1 r1, R2 r2)
if (isInputRange!R1 && isInputRange!R2)
{
Expand Down

0 comments on commit 7e2e705

Please sign in to comment.