fix Issue 9836 - std.array.popFront does not work with alias this.

empty, front, popFront, back, popBack should work with alias this type.
This commit is contained in:
k-hara 2013-03-31 00:00:44 +09:00
parent 113526f6b5
commit 53640bf046

View file

@ -407,11 +407,10 @@ assert(a == [ 2, 3 ]);
), $(ARGS), $(ARGS), $(ARGS import std.array;)) ), $(ARGS), $(ARGS), $(ARGS import std.array;))
*/ */
void popFront(A)(ref A a) void popFront(T)(ref T[] a)
if (!isNarrowString!A && isDynamicArray!A && isMutable!A && !is(A == void[])) if (!isNarrowString!(T[]) && !is(T[] == void[]))
{ {
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 " ~ T.stringof);
~ typeof(a[0]).stringof);
a = a[1 .. $]; a = a[1 .. $];
} }
@ -420,16 +419,16 @@ unittest
auto a = [ 1, 2, 3 ]; auto a = [ 1, 2, 3 ];
a.popFront(); a.popFront();
assert(a == [ 2, 3 ]); assert(a == [ 2, 3 ]);
static assert(!__traits(compiles, popFront!(immutable int[])()));
static assert(!__traits(compiles, popFront!(void[])())); static assert(!is(typeof({ int[4] a; popFront(a); })));
static assert(!is(typeof({ immutable int[] a; popFront(a); })));
static assert(!is(typeof({ void[] a; popFront(a); })));
} }
// Specialization for narrow strings. The necessity of // Specialization for narrow strings. The necessity of
// !isStaticArray!A suggests a compiler @@@BUG@@@. void popFront(C)(ref C[] str) @trusted pure nothrow
void popFront(S)(ref S str) @trusted pure nothrow if (isNarrowString!(C[]))
if (isNarrowString!S && isMutable!S && !isStaticArray!S)
{ {
alias ElementEncodingType!S C;
assert(str.length, "Attempting to popFront() past the end of an array of " ~ C.stringof); assert(str.length, "Attempting to popFront() past the end of an array of " ~ C.stringof);
static if(is(Unqual!C == char)) static if(is(Unqual!C == char))
@ -460,26 +459,14 @@ if (isNarrowString!S && isMutable!S && !isStaticArray!S)
else static assert(0, "Bad template constraint."); else static assert(0, "Bad template constraint.");
} }
version(unittest) C[] _eatString(C)(C[] str)
{
while(!str.empty)
str.popFront();
return str;
}
unittest unittest
{ {
string s1 = "\xC2\xA9hello";
s1.popFront();
assert(s1 == "hello");
wstring s2 = "\xC2\xA9hello";
s2.popFront();
assert(s2 == "hello");
string s3 = "\u20AC100";
foreach(S; TypeTuple!(string, wstring, dstring)) foreach(S; TypeTuple!(string, wstring, dstring))
{ {
S s = "\xC2\xA9hello";
s.popFront();
assert(s == "hello");
S str = "hello\U00010143\u0100\U00010143"; S str = "hello\U00010143\u0100\U00010143";
foreach(dchar c; ['h', 'e', 'l', 'l', 'o', '\U00010143', '\u0100', '\U00010143']) foreach(dchar c; ['h', 'e', 'l', 'l', 'o', '\U00010143', '\u0100', '\U00010143'])
{ {
@ -487,11 +474,18 @@ unittest
str.popFront(); str.popFront();
} }
assert(str.empty); assert(str.empty);
static assert(!is(typeof({ immutable S a; popFront(a); })));
static assert(!is(typeof({ typeof(S.init[0])[4] a; popFront(a); })));
} }
static assert(!is(typeof(popFront!(immutable string)))); C[] _eatString(C)(C[] str)
static assert(!is(typeof(popFront!(char[4])))); {
while(!str.empty)
str.popFront();
return str;
}
enum checkCTFE = _eatString("ウェブサイト@La_Verité.com"); enum checkCTFE = _eatString("ウェブサイト@La_Verité.com");
static assert(checkCTFE.empty); static assert(checkCTFE.empty);
enum checkCTFEW = _eatString("ウェブサイト@La_Verité.com"w); enum checkCTFEW = _eatString("ウェブサイト@La_Verité.com"w);
@ -517,8 +511,8 @@ assert(a == [ 1, 2 ]);
), $(ARGS), $(ARGS), $(ARGS import std.array;)) ), $(ARGS), $(ARGS), $(ARGS import std.array;))
*/ */
void popBack(A)(ref A a) void popBack(T)(ref T[] a)
if (isDynamicArray!A && !isNarrowString!A && isMutable!A && !is(A == void[])) if (!isNarrowString!(T[]) && !is(T[] == void[]))
{ {
assert(a.length); assert(a.length);
a = a[0 .. $ - 1]; a = a[0 .. $ - 1];
@ -529,17 +523,18 @@ unittest
auto a = [ 1, 2, 3 ]; auto a = [ 1, 2, 3 ];
a.popBack(); a.popBack();
assert(a == [ 1, 2 ]); assert(a == [ 1, 2 ]);
static assert(!__traits(compiles, popBack!(immutable int[])));
static assert(!__traits(compiles, popBack!(void[]))); static assert(!is(typeof({ immutable int[] a; popBack(a); })));
static assert(!is(typeof({ int[4] a; popBack(a); })));
static assert(!is(typeof({ void[] a; popBack(a); })));
} }
// Specialization for arrays of char // Specialization for arrays of char
@trusted void popBack(A)(ref A a) @trusted void popBack(T)(ref T[] a)
if(isNarrowString!A && isMutable!A) if (isNarrowString!(T[]))
{ {
assert(a.length, "Attempting to popBack() past the front of an array of " ~ assert(a.length, "Attempting to popBack() past the front of an array of " ~ T.stringof);
typeof(a[0]).stringof); a = a[0 .. $ - std.utf.strideBack(a, $)];
a = a[0 .. $ - std.utf.strideBack(a, a.length)];
} }
unittest unittest
@ -563,7 +558,8 @@ unittest
} }
assert(str.empty); assert(str.empty);
static assert(!__traits(compiles, popBack!(immutable S))); static assert(!is(typeof({ immutable S a; popBack(a); })));
static assert(!is(typeof({ typeof(S.init[0])[4] a; popBack(a); })));
} }
} }
@ -588,19 +584,10 @@ assert(a.front == 1);
@property ref T front(T)(T[] a) @property ref T front(T)(T[] a)
if (!isNarrowString!(T[]) && !is(T[] == void[])) if (!isNarrowString!(T[]) && !is(T[] == void[]))
{ {
assert(a.length, "Attempting to fetch the front of an empty array of " ~ assert(a.length, "Attempting to fetch the front of an empty array of " ~ T.stringof);
typeof(a[0]).stringof);
return a[0]; return a[0];
} }
@property dchar front(A)(A a) if (isNarrowString!A)
{
assert(a.length, "Attempting to fetch the front of an empty array of " ~
typeof(a[0]).stringof);
size_t i = 0;
return decode(a, i);
}
unittest unittest
{ {
auto a = [ 1, 2 ]; auto a = [ 1, 2 ];
@ -610,6 +597,16 @@ unittest
immutable b = [ 1, 2 ]; immutable b = [ 1, 2 ];
assert(b.front == 1); assert(b.front == 1);
int[2] c = [ 1, 2 ];
assert(c.front == 1);
}
@property dchar front(T)(T[] a) if (isNarrowString!(T[]))
{
assert(a.length, "Attempting to fetch the front of an empty array of " ~ T.stringof);
size_t i = 0;
return decode(a, i);
} }
/** /**
@ -631,8 +628,7 @@ assert(a.back == 3);
*/ */
@property ref T back(T)(T[] a) if (!isNarrowString!(T[])) @property ref T back(T)(T[] a) if (!isNarrowString!(T[]))
{ {
assert(a.length, "Attempting to fetch the back of an empty array of " ~ assert(a.length, "Attempting to fetch the back of an empty array of " ~ T.stringof);
typeof(a[0]).stringof);
return a[$ - 1]; return a[$ - 1];
} }
@ -645,14 +641,15 @@ unittest
immutable b = [ 1, 2, 3 ]; immutable b = [ 1, 2, 3 ];
assert(b.back == 3); assert(b.back == 3);
int[3] c = [ 1, 2, 3 ];
assert(c.back == 3);
} }
// Specialization for strings // Specialization for strings
@property dchar back(A)(A a) @property dchar back(T)(T[] a) if (isNarrowString!(T[]))
if(isDynamicArray!A && isNarrowString!A)
{ {
assert(a.length, "Attempting to fetch the back of an empty array of " ~ assert(a.length, "Attempting to fetch the back of an empty array of " ~ T.stringof);
typeof(a[0]).stringof);
size_t i = a.length - std.utf.strideBack(a, a.length); size_t i = a.length - std.utf.strideBack(a, a.length);
return decode(a, i); return decode(a, i);
} }
@ -716,6 +713,25 @@ unittest
assert(overlap(c, d.idup).empty); assert(overlap(c, d.idup).empty);
} }
unittest // bugzilla 9836
{
// range primitives for array should work with alias this types
struct Wrapper
{
int[] data;
alias data this;
@property Wrapper save() { return this; }
}
auto w = Wrapper([1,2,3,4]);
std.array.popFront(w); // should work
static assert(isInputRange!Wrapper);
static assert(isForwardRange!Wrapper);
static assert(isBidirectionalRange!Wrapper);
static assert(isRandomAccessRange!Wrapper);
}
/+ /+
Commented out until the insert which has been deprecated has been removed. Commented out until the insert which has been deprecated has been removed.
I'd love to just remove it in favor of insertInPlace, but then code would then I'd love to just remove it in favor of insertInPlace, but then code would then