Function scopeLimitCalls

Limit the number of times a function can be called.

LimitCalls!(R,T) scopeLimitCalls(R, T...) (
  scope R delegate(T) dg,
  uint maxCalls
);

Given a delegate dg and an integer maxCalls, this function returns a functor with the same parameter and return types as dg, and that forwards up to maxCalls calls to dg. On the maxCalls+1th call it throws an exception. This is useful for algorithms such as scid.nonlinear.findRoot() which may require an arbitrary number of function calls to complete.

void f(int i) { ... }
auto g = limitCalls(&f, 2);

g(0);    // succeeds
g(0);    // succeeds
g(0);    // throws

In the example above, when we're taking the address of f, its context may be copied to the heap. This is a potentially expensive operation. To avoid it, use the unsafe function scopeLimitCalls() instead. This should only be used if you are absolutely sure that the returned delegate never escapes the current scope.

alias void delegate(int) DgType;

// Here, the delegate escapes by being assigned to a variable
// outside the function scope.
DgType someGlobal;
void badIdea1()
{
    void f(int i) { ... }
    someGlobal = scopeLimitCalls(&f, 10);
}

// Here it escapes because we return it.
DgType badIdea2()
{
    void f(int i) { ... }
    return scopeLimitCalls(&f, 10);
}