Comment #0 by qs.il.paperinik — 2019-01-19T21:01:11Z
When opApply overloads are considered for foreach resolution, that have different ref-ness, the better match should be taken.
Currently, the compiler issues an ambiguity error.
There are two cases: When inferring the iteration variable type, and with explicit types on the iteration variable.
The case for inference:
struct Test
{
const(int*) ptr;
int opApply(scope int delegate(const(int)*) callback)
{
return callback(ptr);
}
int opApply(scope int delegate(ref const(int*)) callback)
{
return callback(ptr);
}
}
void main()
{
Test t = Test(new const int(1));
foreach (p; t)
{
pragma(msg, typeof(p)); // should be const(int)*
pragma(msg, __traits(isRef, p)); // should be false
}
foreach (ref p; t)
{
pragma(msg, typeof(p)); // should be const(int*)
pragma(msg, __traits(isRef, p)); // should be true
}
}
Making the types explicit solves this because the types aren't exactly the same.
For explicit types on the iteration variable, change the first opApply overload to take const(int*). The compiler issues an ambiguity error while there is clearly a better overload for each of them. Calling opApply directly works:
struct Test
{
const(int*) ptr;
int opApply(scope int delegate(const(int*)) callback)
{
return callback(ptr);
}
int opApply(scope int delegate(ref const(int*)) callback)
{
return callback(ptr);
}
}
void main()
{
t.opApply((const(int*) p)
{
pragma(msg, typeof(p)); // should be const(int*)
pragma(msg, __traits(isRef, p)); // should be false
return 0;
});
t.opApply((ref const(int*) p)
{
pragma(msg, typeof(p)); // should be const(int*)
pragma(msg, __traits(isRef, p)); // should be true
return 0;
});
}
Comment #1 by robert.schadek — 2024-12-13T19:02:04Z