9

Suppose in C++ you're doing too many recursive calls on a recursive function and getting a stack overflow error.

How would you rewrite this in a continuation-passing style to avoid the stack overflow?

I'm having a slight difficulty picturing this in C++.

Rob Kennedy
  • 161,384
  • 21
  • 275
  • 467
achow
  • 1,013
  • 2
  • 12
  • 20
  • 2
    You're not going to get anything but abstract answers for such an abstract question. Maybe you should post the example function that is causing the stack overflow, then you'll get concrete answers on how to fix it. (And personally, I'd try to rewrite the function to use an accumulator before rewriting it to use a continuation...) – ildjarn Oct 27 '11 at 22:57
  • @ildjarn, thanks for the notice. I'm actually looking for an abstract answer. If I use an accumulator, won't I end up rewriting it as normal iteration in C++? – achow Oct 27 '11 at 23:03
  • @highwind7777 : What sort of abstract answer do you expect? "Use a stateful functor"? That seems too high-level to be helpful, but it's hard to think of anything more specific without a more detailed question... Regarding using an accumulator, no, you can stick with recursion as long as your compiler supports TCO. – ildjarn Oct 27 '11 at 23:05

1 Answers1

4

Well that's a rather open ended question, but Eric Lippert wrote a (well two actually) rather long series about exactly this topic. Not exactly the right language, but it should be rather helpful still and give the general idea.

Though implementing CPS in C++ seems like a lot of work just to fix a single recursive function, when you can just use some algorithm to make the function iterative with a queue (you still use basically the same amount of data, but the heap is far less restricted).

ildjarn
  • 62,044
  • 9
  • 127
  • 211
Voo
  • 29,040
  • 11
  • 82
  • 156
  • 1
    I had the distinct benefit of writing both those series in the context of languages that have lexical closures as a built-in language feature. Rewriting C++ code into closures is of course totally achievable, but it will be a bit of a pain. – Eric Lippert Oct 28 '11 at 13:51
  • 1
    @EricLippert You're right I assumed c++11 lambdas, but obviously not everyone (well not even close to the majority) has a compiler that supports lambdas. Without it, it gets much more complicated (use classes and pass those around presumably?). Btw thanks for your great articles - without you I wouldn't even know what CPS is :) – Voo Oct 28 '11 at 14:29
  • 3
    @Voo : Even without C++11 lambdas, there are C++03 libraries that handle this trivially. See e.g. [Boost.Phoenix](http://www.boost.org/libs/phoenix/). – ildjarn Oct 28 '11 at 15:43
  • 1
    Thanks for the link. @EricLippert By rewriting C++ code into closures, do you mean manually keeping closed (bounded) variables alive by passing them down the call chain? – achow Oct 28 '11 at 17:13
  • 1
    @Voo, I think that would be the Java-style way of doing things. In C++, you can get a more elegant closure implementation by taking advantage of function pointers. – achow Oct 28 '11 at 17:19
  • 1
    @highwind7777: There are a number of different ways you could do it. The problem is complicated greatly in C++ because of the lack of automatic garbage collection; knowing precisely what the lifetime of the closure is can be tricky. I have never attempted to do such a thing, and hope never to have to! – Eric Lippert Oct 28 '11 at 17:23
  • 5
    @highwind7777 Function pointers aren't exactly helpful if you want to implement closures. No idea how boost is doing it, but you need storage somewhere and not just a pointer to executable code. – Voo Oct 29 '11 at 03:26