digitalmars.D.learn - inout in opAssert in custom range
- Valentino Giudice (99/99) Aug 29 Consider the following example:
- monkyyy (65/68) Aug 30 I dont think this does what you think it does; I dont use
Consider the following example:
module demo1;
```D
class MyClass
{
int a;
this(int a)
{
this.a = a;
}
}
struct MyRange
{
MyClass[] _items;
this(MyClass[] items)
{
this._items = items;
}
int opApply(scope int delegate(inout MyClass item) dg) inout
{
for (size_t i = 0; i < this._items.length; i++)
{
int result = dg(this._items[i]);
if (result != 0)
{
return result;
}
}
return 0;
}
inout(MyClass) opIndex(size_t i) inout nothrow
{
return this._items[i];
}
size_t length() const nothrow
{
return this._items.length;
}
public alias opDollar = length;
}
void main()
{
MyClass[2] items;
items[0] = new MyClass(1);
items[1] = new MyClass(2);
MyRange r = MyRange(items);
foreach (MyClass item; r)
{
// Operations
}
const MyRange r2 = MyRange(items);
foreach (const MyClass item; r2)
{
// Operations
}
}
```
The idea is that when the range is constant looping should yield
constant objects and when it's mutable it should yield mutable
objects.
The code above leads to the following error:
```
Error: cannot uniquely infer `foreach` argument types
foreach (MyClass item; r)
Error: cannot uniquely infer `foreach` argument types
foreach (const MyClass item; r2)
```
This problem does not occur if I replace the `inout` declaration
of `opApply` with the following:
```D
int opApply(scope int delegate(MyClass item) dg)
{
for (size_t i = 0; i < this._items.length; i++)
{
int result = dg(this._items[i]);
if (result != 0)
{
return result;
}
}
return 0;
}
int opApply(scope int delegate(const MyClass item) dg) const
{
for (size_t i = 0; i < this._items.length; i++)
{
int result = dg(this._items[i]);
if (result != 0)
{
return result;
}
}
return 0;
}
```
This is obviously suboptimal and requires duplication of code.
Is there a way to obtain the desired effect without duplicating
code?
Thank you a lot in advance!
Aug 29
On Sunday, 30 August 2026 at 03:28:49 UTC, Valentino Giudice wrote:int opApply(scope int delegate(MyClass item) dg)int opApply(scope int delegate(const MyClass item) dg) constI dont think this does what you think it does; I dont use keywords that can only make less code work but im pretty sure that const does nothing, the way youve written it is confusing yourself, its applied to the int and futhermore opApplies return is a return code for asm gotos ```d import std; struct bar{ const int i; int j; const int front()=>i+j; void popFront(){j++;} bool empty()=>j>10; } unittest{ foreach(const i;bar(2)){ typeof(i).stringof.writeln; } foreach(i;bar(4)){ typeof(i).stringof.writeln; } } ``` the constness of foreach varibles is part of a constructed for loop; d avoid bidirectional type propganging like c++ or haskell (because those languages are slow and buggy when you use it) --- ```d import std; class MyClass{} struct bar{ int opApply(scope int delegate(MyClass item) dg) { for (size_t i = 0; i < 2; i++) { int result = dg(new MyClass()); if (result != 0) { return result; } } return 0; } } unittest{ foreach(const i;bar()){ typeof(i).stringof.writeln; } foreach(i;bar()){ typeof(i).stringof.writeln; } } ``` ``` const(MyClass) const(MyClass) MyClass MyClass ``` you should probably not use opApply if your trying to be safe (opApplys uses are hacks like hotloading and injecting long distance jumps) its just part of foreach, and foreach makes copies anyway unless you say "ref"
Aug 30








monkyyy <crazymonkyyy gmail.com>