-1

So in Lua you can do something like this

local function start(n)
    return function()
        n = n + 1;
        return n;
    end;
end

print(start(1)()); --> 2

I've heard of templates though I don't want to have an xy problem, or is there another way

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
incapaz
  • 349
  • 1
  • 3
  • 11
  • They are called [Function objects](https://en.cppreference.com/w/cpp/utility/functional) or Functors. It's just any object that provides a `operator()`. – François Andrieux May 21 '19 at 18:13
  • Return a `std::function` or a function pointer. – Jesper Juhl May 21 '19 at 18:14
  • 1
    Closures in C++ have some restrictions that are caused by the lack of Automatic Memory Management. So, you won't get something that is 100% equivalent. – Jörg W Mittag May 21 '19 at 18:15
  • returning function pointer is also work around – Mayur May 21 '19 at 18:17
  • @JörgWMittag care to clarify what you mean by Automatic Memory Management? C++ certainly DOES NOT lack automatic storage duration, for example. – SergeyA May 21 '19 at 18:18
  • @SergeyA: In the Lua example, `n` is captured by reference. In other words, the lifetime of the local variable `n` is extended by an indefinite and unbounded amount of time beyond the lifetime of its enclosing lexical scope. This pretty much *requires* Automatic Memory Management to handle. Lua, Lisp, Scheme, Smalltalk, Ruby, Python, PHP, Haskell, Scala, C♯, F♯, ECMAScript, and countless other languages deal with this without any sort of problem, but in C++, it is not allowed because of the lack of Automatic Memory Management. If C++ *had* Automatic Memory Management, this restriction … – Jörg W Mittag May 21 '19 at 18:28
  • … wouldn't exist (and neither would `delete`) and the equivalent C++ code would just magically work. If you want, you can replace "AMM" with "Garbage Collection", but I think GC is too restrictive. – Jörg W Mittag May 21 '19 at 18:29

2 Answers2

6

In C++ you cannot declare a function inside of another function. Luckily though we can work around that by creating a closure object using a lambda expression. Your code, adapted to that would become

template <typename Integer>
auto start(Integer n)
{
    return [n]() mutable { return ++n; };
}

And then you would use it like

std::cout << start(1)();

There are couple things to note about the above example. First, the capture of n. Since the closure object is be returned out of the scope of start, we have to capture it by value, otherwise the closure will have a dangling reference. Secondly, the use of mutable in the lambda expression. That is there because by default the operator() is const. That means you could not modify n. Using mutable removes the const and allows n to be modified.

NathanOliver
  • 171,901
  • 28
  • 288
  • 402
4

The easiest way is to return a lambda function object:

auto start(int n) {
    return [n]() mutable {
        n = n + 1;
        return n;
    };
}
Guillaume Racicot
  • 39,621
  • 9
  • 77
  • 141