mirror of
https://github.com/dlang/phobos.git
synced 2025-04-27 13:40: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))
|
&& !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)
|
||||||
|
|
14
std/array.d
14
std/array.d
|
@ -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)
|
||||||
|
|
21
std/traits.d
21
std/traits.d
|
@ -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.
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue