mirror of
https://github.com/dlang/phobos.git
synced 2025-04-26 21:22:20 +03:00
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:
parent
dcd1561de3
commit
af1fb0b618
3 changed files with 33 additions and 10 deletions
|
@ -1061,7 +1061,7 @@ $(D !pointsTo(lhs, lhs) && !pointsTo(lhs, rhs) && !pointsTo(rhs, lhs)
|
|||
&& !pointsTo(rhs, rhs))
|
||||
*/
|
||||
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)
|
||||
{
|
||||
|
@ -1120,6 +1120,9 @@ unittest
|
|||
assert(s2.x == 0);
|
||||
assert(s2.c == 'z');
|
||||
assert(s2.y == [ 1, 2 ]);
|
||||
|
||||
immutable int imm1, imm2;
|
||||
static assert(!__traits(compiles, swap(imm1, imm2)));
|
||||
}
|
||||
|
||||
unittest
|
||||
|
@ -1147,6 +1150,9 @@ unittest
|
|||
swap(h1, h2);
|
||||
assert(h1.noCopy.n == 65 && h1.noCopy.s == null);
|
||||
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)
|
||||
|
|
14
std/array.d
14
std/array.d
|
@ -256,10 +256,6 @@ void main()
|
|||
return a;
|
||||
}
|
||||
|
||||
private template notConst(T) {
|
||||
enum notConst = !is(T == const) && !is(T == immutable);
|
||||
}
|
||||
|
||||
/**
|
||||
Implements the range interface primitive $(D popFront) for built-in
|
||||
arrays. Due to the fact that nonmember functions can be called with
|
||||
|
@ -279,7 +275,7 @@ void main()
|
|||
*/
|
||||
|
||||
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;
|
||||
assert(a.length, "Attempting to popFront() past the end of an array of "
|
||||
|
@ -299,7 +295,7 @@ unittest
|
|||
}
|
||||
|
||||
void popFront(A)(ref A a)
|
||||
if(isNarrowString!A && notConst!A)
|
||||
if(isNarrowString!A && isMutable!A)
|
||||
{
|
||||
alias typeof(a[0]) T;
|
||||
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)
|
||||
if(isDynamicArray!A && !isNarrowString!A && notConst!A && !is(A == void[]))
|
||||
if(isDynamicArray!A && !isNarrowString!A && isMutable!A && !is(A == void[]))
|
||||
{
|
||||
assert(a.length);
|
||||
a = a[0 .. $ - 1];
|
||||
|
@ -358,7 +354,7 @@ unittest
|
|||
}
|
||||
|
||||
void popBack(A)(ref A a)
|
||||
if(is(A : const(char)[]) && notConst!A)
|
||||
if(is(A : const(char)[]) && isMutable!A)
|
||||
{
|
||||
immutable n = a.length;
|
||||
const p = a.ptr + n;
|
||||
|
@ -400,7 +396,7 @@ unittest
|
|||
}
|
||||
|
||||
void popBack(A)(ref A a)
|
||||
if(is(A : const(wchar)[]) && notConst!A)
|
||||
if(is(A : const(wchar)[]) && isMutable!A)
|
||||
{
|
||||
assert(a.length);
|
||||
if (a.length == 1)
|
||||
|
|
21
std/traits.d
21
std/traits.d
|
@ -2774,6 +2774,27 @@ unittest {
|
|||
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.
|
||||
*/
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue