Bug 8330 – std.algorithm.find doesn't handle reference type ranges correctly
Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P2
Component
phobos
Product
D
Version
D2
Platform
All
OS
All
Creation time
2012-07-01T01:40:00Z
Last change time
2015-06-09T05:14:45Z
Assigned to
issues.dlang
Creator
issues.dlang
Comments
Comment #0 by issues.dlang — 2012-07-01T01:40:44Z
This code
import std.algorithm;
import std.range;
void main()
{
auto arr = [1, 2, 3, 4, 1, 9, 12, 42];
assert(find(arr, [9, 12, 42]) == [9, 12, 42]);
auto range = refRange(&arr);
assert(equal(*find(range, [9, 12, 42]).ptr, [9, 12, 42]));
}
fails, giving
core.exception.AssertError@q(10): Assertion failure
----------------
./q(_d_assertm+0x26) [0x43aa4e]
./q() [0x438826]
./q(_Dmain+0x1f8) [0x4312d8]
./q(extern (C) int rt.dmain2.main(int, char**).void runMain()+0x1c) [0x43b2e4]
./q(extern (C) int rt.dmain2.main(int, char**).void tryExec(scope void delegate())+0x2a) [0x43ac5e]
./q(extern (C) int rt.dmain2.main(int, char**).void runAll()+0x3b) [0x43b32b]
./q(extern (C) int rt.dmain2.main(int, char**).void tryExec(scope void delegate())+0x2a) [0x43ac5e]
./q(main+0xd1) [0x43abe9]
/lib/libc.so.6(__libc_start_main+0xf5) [0x7fd9af788455]
----------------
If you print out the result of the find that fails, you get [12, 49]. I believe that the problem is with this particular overload of find:
R1 find(alias pred = "a == b", R1, R2)(R1 haystack, R2 needle)
if (isRandomAccessRange!R1 && hasLength!R1 && isBidirectionalRange!R2
&& is(typeof(binaryFun!pred(haystack.front, needle.front)) : bool))
It appears that whenever you use a reference type haystack, and your needle has a length greater than 2, the result is missing one element on its front. It works with needles of lengthe 2 or less, and it works fine with value type ranges just fine but not reference types. And it also fails with
import std.algorithm;
import std.range;
import std.stdio;
class C
{
this(int[] arr)
{
_arr = arr;
}
bool empty() {return _arr.empty;}
@property auto save() {return new C(_arr);}
@property int front() {return _arr.front;}
void popFront() {_arr.popFront();}
@property int back() {return _arr.back;}
void popBack() {_arr.popBack();}
@property size_t length() {return _arr.length;}
auto opIndex(size_t i) { return _arr[i]; }
auto opSlice(size_t i, size_t j) { return new C(_arr[i .. j]); }
auto opSlice() { return save; }
int[] _arr;
}
static assert(isRandomAccessRange!C);
void main()
{
auto arr = [1, 2, 3, 4, 1, 9, 12, 42];
auto c = new C(arr);
auto range = refRange(&arr);
assert(equal(find(c, [9, 12, 42]), [9, 12, 42]));
}
so it's not a bug in RefRange.
Comment #1 by john.loughran.colvin — 2013-07-11T15:52:54Z
No longer occurs. Both examples run fine on git master, although this could well have been fixed ages ago.