3

In Template Meta Programming if a recursion is wrongly implemented with a resulting infinite loop, can the language compiler detect it? Or will the compiler just encounter an eventual stack overflow and crashe? My bet would be that compiler cannot detect this because doing so would violate the undecideability of the halting problem.

Am I right with the conclusion? Of course I could try this out with a piece of code, but I would like to hear more qualified thinking in this case.

Edit : Thanks guys, I get a general idea that my inference on the computation theory aspect of tmp was not wrong. I also understand that compiler implementations can have arbitrary recursion depth limits(Of course I reiterate that I could have tested this second part, but it was only my side-point).

PermanentGuest
  • 5,213
  • 2
  • 27
  • 36
  • Yes, this is akin to the halting problem. – Oliver Charlesworth Jun 03 '12 at 19:21
  • exactly what prevented you from just checking with some real compilers? – Cheers and hth. - Alf Jun 03 '12 at 19:25
  • @Alf, checking with a compiler will give me a result with that compiler. I don't want to just test how a compiler can cope with this problem. I'm more interested in the theory of it.. – PermanentGuest Jun 03 '12 at 19:28
  • There is no infinite recursion for template instantiation, templates are only instantiated once for a given set of arguments and the set of argument values is finite. – K-ballo Jun 03 '12 at 19:32
  • @K-ballo how about using a template int as argument, then call the same function using that int-1? If you don't provide a base case, you'll have an infinite template instantiation. I've seen that on gcc at least. – mfontanini Jun 03 '12 at 19:38
  • @mfontanini: Is not an infinite template instantiation, eventually the int will wrap around. Of course we will never get to see that, as the implementation limits would be hit much much sooner than that. – K-ballo Jun 03 '12 at 19:39
  • 1
    @K-ballo: There are ways of creating infinite template instantiations, consider a template `X` that internally has a member of type `X>`, for example... `X` will instantiate `X>` which instantiates `X>>`... – David Rodríguez - dribeas Jun 03 '12 at 19:55

6 Answers6

3

You can't in general detect such infinite recursion; template metaprogramming is Turing capable, and to such detection would amount to solving the halting problem. As is usual with Turing hard problems, that doesn't mean you can't detect certain cases.

I think the compilers tend to have a minimum number of levels that templates may nest established by the standard, and a maximum number at which point they'll diagnose a nesting-too-deep.

Ira Baxter
  • 93,541
  • 22
  • 172
  • 341
2

The standard states that implementations can (and effectively will) limit some quantities that among others include:

Annex B

  • Recursively nested template instantiations, including substitution during template argument deduction (14.8.2)

The compiler will most probably bail out once it's predefined limit for this quantity is reached, with an appropriate error message.

Community
  • 1
  • 1
David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489
1

Template metaprogramming is Turing complete, so yes, any compiler that is able to detect infinite loops in all cases (without mistakenly classifying terminating loops as infinite) would be able to solve the halting problem.

But just like regular code, some infinite loops could be detected. I don't think any compilers would check, though, and instead will just complain if you exceed some maximum recursion depth.

  • The language is Turing complete, the implementation itself has limits so it isn't. – K-ballo Jun 03 '12 at 19:24
  • You mean "no", it can't detect the loop. – vz0 Jun 03 '12 at 19:25
  • Right: I mean "Yes, you are correct your belief that it can't detect the loop" –  Jun 03 '12 at 19:27
  • 1
    This is not necessarily true... compilers have a limit on template instantiations, and that means that it only needs to *count* how many instantiations it's done and stop there. This is not detecting potentially infinite recursion, but just limiting at it's own measure of infinity. – David Rodríguez - dribeas Jun 03 '12 at 19:27
  • 1
    @DavidRodríguez-dribeas What if the MAX_RECURSIVE_LIMIT+1 recursive call is the one that makes the program actually end? That's what Halting Problem is about. – vz0 Jun 03 '12 at 19:29
  • I was once told that *infinity* is just one step further than the furthest you can get. If that is where the algorithm stops, it does not really matter, it is just one step further than where the compiler can get, it will fail with an appropriate message and leave it up to you to decide what to do from there (some compilers allow increasing the limit). From a practical standpoint, if the compiler only allows MAX_RECURSION_LIMIT, then MAX_RECURSION_LIMIT+1 *is* infinity. – David Rodríguez - dribeas Jun 03 '12 at 19:31
1

Yes, it is usually detectable

Although the halting problem is undecidable in the general case, it is certainly decidable for many if not most specific cases.

And the easy, obvious, way to do that: limit the amount of recursion allowed.

So the answer, in general, is the first: it detects the infinite loop.

(It's easy to detect programs that don't stop if you can accept being wrong in certain cases. After all, unlimited recursion is not allowed by any compiler.)

DigitalRoss
  • 143,651
  • 25
  • 248
  • 329
0

Your are correct. Detecting an infinite recursion without limiting the recursion stack frames on template meta programming would mean finding an alternative solution to the halting problem.

There are a few special cases which are, in theory, detectable. For example, if you can ensure referential transparency on the recursion and if the last function call receives the same parameters as the actual one, you are on an infinite recursive call. C++ offers no referential transparency warranty on template meta programming.

vz0
  • 32,345
  • 7
  • 44
  • 77
  • I can detect some infinite recursions without limiting anything, but I can't solve the halting problem. A compiler analyzes on a graph level, too; loops in graphs are detectable. Solving the halting problem implies detection of infinite loops, NOT the other way around. – comonad Jun 03 '12 at 20:02
  • 1
    The language offers not *referential transparency*, but it kind of does... each template must be instantiated *once* in each translation unit, and that means that the compiler must keep track of all of the *instantiated* templates. The infinite recursion would kick in *before* the instantiation completes, so as you say, this does not mean that the standard mandates detecting it, but since it must track the instantiations it is just one step away from doing it. Additionally, this does not cover all cases either... – David Rodríguez - dribeas Jun 03 '12 at 20:12
0

Of course, it IS POSSIBLE to detect infinite-loops due to referential transparency. That is trivial, but I didn't test which compiler does that.

On the other hand, it is either unlikely or impossible to detect, iff the recursion generates infinite DIFFERENT template instantiations (which do not loop on the instantiation level). This is due Turung completeness.

For each template instantiation the compiler will generate a finite tree graph where every node is a template instantiation. As soon as the compiler detects a back-edge/that the graph is no tree due to a loop, it should abort. Infinite graphs/trees (Halting problem) will probably be detected with timeouts / limited graph size.

comonad
  • 5,134
  • 2
  • 33
  • 31