www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Cannot call find with haystack elements having a explicit copy

reply Per =?UTF-8?B?Tm9yZGzDtnc=?= <per.nordlow gmail.com> writes:
The adding of copy construtors to `Service` defined as

```d
 safe struct Service {
     this(ref return scope typeof(this) rhs) {}
     this(const ref return scope typeof(this) rhs) const {}
}

 safe struct Session {
     void openAndGetService(in string key) scope {
         import std.algorithm.searching : find;
         auto hit = _pairs.find!((x) => x.key == key)();
     }
     private Pair[] _pairs;
     private struct Pair {
         string key;
         Service service;
     }
}
```

makes a call to find error as

```
copy_ctor_find_fail.d(9): Error: template 
`std.algorithm.searching.find` cannot deduce function from 
argument types `!((x) => x.key == key)(Pair[])`, candidates are:
auto hit = _pairs.find!((x) => x.key == key)();
^
std/algorithm/searching.d(1559):        `find(alias pred = "a == 
b", InputRange, Element)(InputRange haystack, scope Element 
needle)`
InputRange find(alias pred = "a == b", InputRange, 
Element)(InputRange haystack, scope Element needle)
^
std/algorithm/searching.d(1827):        `find(alias pred, 
InputRange)(InputRange haystack)`
with `pred = __lambda2,
InputRange = Pair[]`
must satisfy the following constraint:
`       isInputRange!InputRange`
InputRange find(alias pred, InputRange)(InputRange haystack)
^
std/algorithm/searching.d(1881):        `find(alias pred = "a == 
b", R1, R2)(R1 haystack, scope R2 needle)`
R1 find(alias pred = "a == b", R1, R2)(R1 haystack, scope R2 
needle)
^
std/algorithm/searching.d(2340):        `find(alias pred = "a == 
b", Range, Ranges...)(Range haystack, Ranges needles)`
with `pred = __lambda2,
Range = Pair[],
Ranges = ()`
must satisfy the following constraint:
`       Ranges.length > 1`
Tuple!(Range, size_t) find(alias pred = "a == b", Range, 
Ranges...)
^
std/algorithm/searching.d(2455):        `find(RandomAccessRange, 
alias pred, InputRange)(RandomAccessRange haystack, scope 
BoyerMooreFinder!(pred, InputRange) needle)`
RandomAccessRange find(RandomAccessRange, alias pred, InputRange)(
^```
Using

```d
auto hit = _pairs.find!((scope const ref x) => x.key == key)();
```

fails in the same way. What's wrong?
Jul 15 2021
next sibling parent Per =?UTF-8?B?Tm9yZGzDtnc=?= <per.nordlow gmail.com> writes:
On Thursday, 15 July 2021 at 11:08:25 UTC, Per Nordlöw wrote:
 fails in the same way. What's wrong?
```d safe struct Service { this(ref typeof(this) rhs) {} this(const ref typeof(this) rhs) const {} } ``` also fails. On the other hand, using a postblit as ``` safe struct Service { this(this) {} } ``` passes.
Jul 15 2021
prev sibling next sibling parent Per =?UTF-8?B?Tm9yZGzDtnc=?= <per.nordlow gmail.com> writes:
On Thursday, 15 July 2021 at 11:08:25 UTC, Per Nordlöw wrote:
 The adding of copy construtors to `Service` defined as

 ```d
  safe struct Service {
     this(ref return scope typeof(this) rhs) {}
     this(const ref return scope typeof(this) rhs) const {}
 }
Using `inout` as ```d safe struct Service { this(inout ref typeof(this) rhs) inout {} } ``` works.
Jul 15 2021
prev sibling parent RazvanN <razvan.nitu1305 gmail.com> writes:
On Thursday, 15 July 2021 at 11:08:25 UTC, Per Nordlöw wrote:
 The adding of copy construtors to `Service` defined as

 ```d
  safe struct Service {
     this(ref return scope typeof(this) rhs) {}
     this(const ref return scope typeof(this) rhs) const {}
 }

  safe struct Session {
     void openAndGetService(in string key) scope {
         import std.algorithm.searching : find;
         auto hit = _pairs.find!((x) => x.key == key)();
     }
     private Pair[] _pairs;
     private struct Pair {
         string key;
         Service service;
     }
 }
 ```
struct Pair will have an inout(inout) copy constructor defined the following way: this(inout ref return scope typeof(this) rhs) inout { key = rhs.key; service = rhs.service; } `service = rhs.service` will be rewritten to service.__cpctor(rhs.service), but since Service does not define an inout copy constructor it will fail to typecheck and the compiler will annotate it with disable. Therefore, Pair will become uncopyable. This will result in isInputRange failing on Pair[] (more specifically, this constraints from isInputRange: is(typeof((return ref R r) => r.front)). If the copy constructor of Service is inout(inout), the generated copy constructor of Pair will be succesfully typechecked and everything will work. For more context, please see this issue [1] and more specifically, this comment [2]. Cheers, RazvanN [1] https://issues.dlang.org/show_bug.cgi?id=20876 [2] https://issues.dlang.org/show_bug.cgi?id=20876#c4
Jul 15 2021