How do you safely deal with range.front?
Ali Çehreli
acehreli at yahoo.com
Mon Jan 1 04:18:29 UTC 2018
On 12/30/2017 11:00 AM, aliak wrote:
> Instead of this:
> auto result = range.op!f;
> if (!result.empty) {
> result.front.method();
> }
>
> This:
> range.op!f.ifFront.method();
>
>
> In the above scenario I only want method to be called if the pipeline
> resulted in any element left in the range.
If you're fine with specifying the function as a template argument, the
following works. (As seen with 's => s.foo()' below, you have to use a
lambda for member functions anyway.)
auto ifFront(alias func, R)(R range) {
import std.traits : isArray;
static if (isArray!R) {
import std.array : empty, front;
}
if (!range.empty) {
func(range.front);
}
}
unittest {
size_t executed;
struct S {
size_t *e;
this(ref size_t e) {
this.e = &e;
}
void foo() {
++(*e);
}
}
auto foo(int) {
++executed;
}
// Non-empty array; should be called
auto a = [1];
a.ifFront!foo;
assert(executed == 1);
// Empty array; should not be called
int[] b;
b.ifFront!foo;
assert(executed == 1);
// Non-empty S array; should be called
auto c = [ S(executed) ];
c.ifFront!(s => s.foo());
assert(executed == 2);
// Empty S array; should not be called
S[] d;
d.ifFront!(s => s.foo());
assert(executed == 2);
}
void main() {
}
Ali
More information about the Digitalmars-d-learn
mailing list