digitalmars.D.learn - input range with non copyable element
- vit (51/51) Aug 08 2021 Hello, is there reason why elements of input range must be
- Mathias LANG (14/16) Aug 08 2021 By design, not that I can think of. But it is assumed all over
- vit (13/30) Aug 09 2021 Look like I am not the first who has this problem:
Hello, is there reason why elements of input range must be
copyable?
For example this example works and copy ctor is never called:
```d
import std.algorithm : map;
import std.range;
struct Foo{
int i;
this(scope ref typeof(this) rhs)pure nothrow safe nogc{
//this.i = rhs.i;
assert(0, "no copy");
}
disable this(scope const ref typeof(this) rhs)pure nothrow
safe nogc;
}
void main(){
Foo[] foos = [Foo(1), Foo(2), Foo(3)];
//this work (copy ctor is never called):
{
auto tmp = foos
.map!((ref foo) => foo.i)
.array;
}
}
```
This doesn't work:
```d
void main(){
const(Foo)[] foos = [Foo(1), Foo(2), Foo(3)];
//error:
{
auto tmp = foos
.map!((ref foo) => foo.i)
.array;
}
}
```
Source of my problem is in `isInputRange`:
```d
import std.range;
import std.traits : ReturnType;
alias R = const(Foo)[];
//enum bool isInputRange(R) =
static assert(is(typeof(R.init) == R)); ///OK
static assert(is(ReturnType!((R r) => r.empty) == bool)); ///OK
static assert(is(typeof((return ref R r) =>
r.front))); ///ERROR, copy result of front
static assert(!is(ReturnType!((R r) => r.front) == void)); ///OK
static assert(is(typeof((R r) => r.popFront))); ///OK
```
Is it possible to make lambda return `auto ref`?
Aug 08 2021
On Sunday, 8 August 2021 at 18:36:02 UTC, vit wrote:Hello, is there reason why elements of input range must be copyable?By design, not that I can think of. But it is assumed all over the place, unfortunately. You can make your `front` method return by `ref`, but you're still going to get bitten as soon as you do any `std.algorithm`-based operation, as storage classes are not inferred (https://issues.dlang.org/show_bug.cgi?id=9423) and things get passed by value to your delegates by default. The problem can also show up when you `foreach` over a range (https://issues.dlang.org/show_bug.cgi?id=15413). And finally, `std.algorithm` need to support it. So currently you'll have to jump through a lot of hops to get it to work. It'll be much easier to use your own `map` & co to get the job done for the time being. Hopefully at some point in the near future that won't be needed anymore.
Aug 08 2021
On Monday, 9 August 2021 at 02:47:40 UTC, Mathias LANG wrote:On Sunday, 8 August 2021 at 18:36:02 UTC, vit wrote:Look like I am not the first who has this problem: https://issues.dlang.org/show_bug.cgi?id=14478 I copy part of `std.algorithm` I use and change `isInputRange` to: ```d enum bool isInputRange(R) = true && is(typeof(R.init) == R) ///no change && is(ReturnType!((R r) => r.empty) == bool) ///no change && is(typeof((return ref R r) => (auto ref x){}(r.front))) ///Before: , is(typeof((return ref R r) => r.front)) && !is(ReturnType!((R r) => r.front) == void) ///no change && is(typeof((R r) => r.popFront)); ///no changeHello, is there reason why elements of input range must be copyable?By design, not that I can think of. But it is assumed all over the place, unfortunately. You can make your `front` method return by `ref`, but you're still going to get bitten as soon as you do any `std.algorithm`-based operation, as storage classes are not inferred (https://issues.dlang.org/show_bug.cgi?id=9423) and things get passed by value to your delegates by default. The problem can also show up when you `foreach` over a range (https://issues.dlang.org/show_bug.cgi?id=15413). And finally, `std.algorithm` need to support it. So currently you'll have to jump through a lot of hops to get it to work. It'll be much easier to use your own `map` & co to get the job done for the time being. Hopefully at some point in the near future that won't be needed anymore.
Aug 09 2021








vit <vit vit.vit>