Bug 4654 – Cannot overload range iteration against opApply iteration

Status
RESOLVED
Resolution
INVALID
Severity
normal
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
Other
OS
Windows
Creation time
2010-08-16T08:21:22Z
Last change time
2020-03-21T03:56:38Z
Assigned to
No Owner
Creator
David Simcha

Comments

Comment #0 by dsimcha — 2010-08-16T08:21:22Z
The following code doesn't compile even though there is no ambiguity: struct Range { uint num; @property uint front() { return num; } void popFront() { num++; } bool empty() { return num >= 10; } int opApply(int delegate(ref int, ref int, ref int) dg) { int res; foreach(i; 0..10) { res = dg(i, i, i); if(res) break; } return res; } } void main() { Range range; foreach(elem; range) {} // Doesn't work. foreach(e1, e2, e3; range) {} // Works if previous line commented out. } test.d(28): Error: cannot infer type for elem
Comment #1 by lt.infiltrator — 2015-10-31T21:53:43Z
The issue is that the opApply delegate takes three ints, so obviously it won't compile if you pass only one. I know that with AAs you can do both foreach(value) and foreach(key,value); but I'm not sure how exactly that's implemented. Having said that, this bug report does highlight a problem with the error message and it should stay open until it is fixed. Current (2.068) message: Error: cannot infer argument types, expected 3 arguments, not 1 As for what it should be, I don't really have any good suggestions.
Comment #2 by b2.temp — 2015-11-01T04:55:21Z
(In reply to Infiltrator from comment #1) > The issue is that the opApply delegate takes three ints, so obviously it > won't compile if you pass only one. I know that with AAs you can do both > foreach(value) and foreach(key,value); but I'm not sure how exactly that's > implemented. > > Having said that, this bug report does highlight a problem with the error > message and it should stay open until it is fixed. > > Current (2.068) message: > Error: cannot infer argument types, expected 3 arguments, not 1 > > As for what it should be, I don't really have any good suggestions. No you don't get the point. The problem is that dmd recognizes both InputRange or opApply() as foreach aggregate argument. The OP expected the InpuRange to be used in the first case and opApply in the second: --- foreach(elem; range) {} // should use front/empty/popFront foreach(e1, e2, e3; range) {} // should use opApply --- Actually this issue is invalid because the behavior is specified: http://dlang.org/statement.html#foreach-with-ranges > if the aggregate expression is a struct or class object, but the opApply for > foreach, or opApplyReverse foreach_reverse do not exist, then iteration over > struct and class objects can be done with range primitives Meaning: if opApply is not present then look for InputRange primitives.