Constrain swap() with isMutable!T so that const objects should not be swapped. std.traits.isMutable is undocumented for now.

This commit is contained in:
Shin Fujishiro 2010-11-18 21:45:18 +00:00
parent dcd1561de3
commit af1fb0b618
3 changed files with 33 additions and 10 deletions

View file

@ -1061,7 +1061,7 @@ $(D !pointsTo(lhs, lhs) && !pointsTo(lhs, rhs) && !pointsTo(rhs, lhs)
&& !pointsTo(rhs, rhs)) && !pointsTo(rhs, rhs))
*/ */
void swap(T)(ref T lhs, ref T rhs) @trusted pure nothrow void swap(T)(ref T lhs, ref T rhs) @trusted pure nothrow
if (!is(typeof(T.init.proxySwap(T.init)))) if (isMutable!T && !is(typeof(T.init.proxySwap(T.init))))
{ {
static if (hasElaborateAssign!T) static if (hasElaborateAssign!T)
{ {
@ -1120,6 +1120,9 @@ unittest
assert(s2.x == 0); assert(s2.x == 0);
assert(s2.c == 'z'); assert(s2.c == 'z');
assert(s2.y == [ 1, 2 ]); assert(s2.y == [ 1, 2 ]);
immutable int imm1, imm2;
static assert(!__traits(compiles, swap(imm1, imm2)));
} }
unittest unittest
@ -1147,6 +1150,9 @@ unittest
swap(h1, h2); swap(h1, h2);
assert(h1.noCopy.n == 65 && h1.noCopy.s == null); assert(h1.noCopy.n == 65 && h1.noCopy.s == null);
assert(h2.noCopy.n == 31 && h2.noCopy.s == "abc"); assert(h2.noCopy.n == 31 && h2.noCopy.s == "abc");
const NoCopy const1, const2;
static assert(!__traits(compiles, swap(const1, const2)));
} }
void swapFront(R1, R2)(R1 r1, R2 r2) void swapFront(R1, R2)(R1 r1, R2 r2)

View file

@ -256,10 +256,6 @@ void main()
return a; return a;
} }
private template notConst(T) {
enum notConst = !is(T == const) && !is(T == immutable);
}
/** /**
Implements the range interface primitive $(D popFront) for built-in Implements the range interface primitive $(D popFront) for built-in
arrays. Due to the fact that nonmember functions can be called with arrays. Due to the fact that nonmember functions can be called with
@ -279,7 +275,7 @@ void main()
*/ */
void popFront(A)(ref A a) void popFront(A)(ref A a)
if(!isNarrowString!A && isDynamicArray!A && notConst!A && !is(A == void[])) if(!isNarrowString!A && isDynamicArray!A && isMutable!A && !is(A == void[]))
{ {
alias typeof(A[0]) T; alias typeof(A[0]) T;
assert(a.length, "Attempting to popFront() past the end of an array of " assert(a.length, "Attempting to popFront() past the end of an array of "
@ -299,7 +295,7 @@ unittest
} }
void popFront(A)(ref A a) void popFront(A)(ref A a)
if(isNarrowString!A && notConst!A) if(isNarrowString!A && isMutable!A)
{ {
alias typeof(a[0]) T; alias typeof(a[0]) T;
assert(a.length, "Attempting to popFront() past the end of an array of " assert(a.length, "Attempting to popFront() past the end of an array of "
@ -340,7 +336,7 @@ void main()
*/ */
void popBack(A)(ref A a) void popBack(A)(ref A a)
if(isDynamicArray!A && !isNarrowString!A && notConst!A && !is(A == void[])) if(isDynamicArray!A && !isNarrowString!A && isMutable!A && !is(A == void[]))
{ {
assert(a.length); assert(a.length);
a = a[0 .. $ - 1]; a = a[0 .. $ - 1];
@ -358,7 +354,7 @@ unittest
} }
void popBack(A)(ref A a) void popBack(A)(ref A a)
if(is(A : const(char)[]) && notConst!A) if(is(A : const(char)[]) && isMutable!A)
{ {
immutable n = a.length; immutable n = a.length;
const p = a.ptr + n; const p = a.ptr + n;
@ -400,7 +396,7 @@ unittest
} }
void popBack(A)(ref A a) void popBack(A)(ref A a)
if(is(A : const(wchar)[]) && notConst!A) if(is(A : const(wchar)[]) && isMutable!A)
{ {
assert(a.length); assert(a.length);
if (a.length == 1) if (a.length == 1)

View file

@ -2774,6 +2774,27 @@ unittest {
static assert(isIterable!(Range)); static assert(isIterable!(Range));
} }
/*
* Returns true if T is not const or immutable. Note that isMutable is true for
* string, or immutable(char)[], because the 'head' is mutable.
*/
template isMutable(T)
{
enum isMutable = !is(T == const) && !is(T == immutable);
}
unittest
{
static assert(isMutable!int);
static assert(isMutable!string);
static assert(isMutable!(shared int));
static assert(isMutable!(shared const(int)[]));
static assert(!isMutable!(const int));
static assert(!isMutable!(shared(const int)));
static assert(!isMutable!(immutable string));
}
/** /**
* Tells whether the tuple T is an expression tuple. * Tells whether the tuple T is an expression tuple.
*/ */