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