For the following code:
```
struct S {
int opApply(Dg)(scope Dg dg)
{
return dg(1);
}
}
int main()
{
foreach(int i; S())
{
return i;
}
return 0;
}
```
The compiler interprets this as:
```
foreach(ref int i; S())
```
Which is wrongly inferred.
Comment #1 by dlang-bot — 2022-05-16T16:48:11Z
@ljmf00 created dlang/dmd pull request #14132 "fix(statementsem): foreach shouldn't infer ref on templated opApply" fixing this issue:
- fix(statementsem): foreach shouldn't infer ref on templated opApply
When a foreach with templated opApply, the compiler infers the
following:
```d
foreach(ref int i; S())
```
Even if you explicitly type it as non-ref.
Fix issue 23116.
Reference: https://issues.dlang.org/show_bug.cgi?id=23116
Signed-off-by: Luís Ferreira <[email protected]>
https://github.com/dlang/dmd/pull/14132
Comment #2 by dkorpel — 2022-05-16T17:22:55Z
Does inferring ref result in actual behavioral problems?
Comment #3 by contact — 2022-05-16T17:28:41Z
(In reply to Dennis from comment #2)
> Does inferring ref result in actual behavioral problems?
It is. It should use the available overload. In my case, I have something like:
```
[ParameterStorageClassTuple!Dg].all!(stc => !(stc & STC.ref_))
```
It should fall into the usable case, like it does without templating it.
Comment #4 by contact — 2022-05-16T17:55:10Z
Doing fallback of the overload manually can be a workaround for this:
```
int opApply(Dg : int delegate(ref ubyte))(scope Dg dg)
{
enum attrs = functionAttributes!Dg;
alias nonRefDg = SetFunctionAttributes!(int delegate(ubyte), functionLinkage!Dg, attrs);
foreach(ubyte i; &this.opApply!(nonRefDg)) // use the correct overload
if(auto ret = dg(i)) return ret;
return 0;
}
int opApply(Dg : int delegate(ubyte))(scope Dg dg)
{
// ...
}
```
@Bolpat created dlang/dlang.org pull request #3859 "Specify `opApply` as an alias to a function template instance" fixing this issue:
- Fix Bugzilla Issues 23666, 17953, 23116, and 24633
https://github.com/dlang/dlang.org/pull/3859
Comment #7 by robert.schadek — 2024-12-13T19:22:50Z