Proving that C++'s grammar is undecidable
medium.com
medium.com
This means that this program does not prove that parsing C++ is undecidable in the way the author thinks. There is no term that is a type or a value depending on the solution to an undecidable problem. Instead, there is a term that can not be resolved in finite time. This is a necessity property of pretty much any Turing-complete metaprogramming system.
(What I think is actually going on that’s a bit unique to C++ is that C++ cannot be parsed unambiguously. The fact that the grammar depends on whether a term is a type or value and that you can’t determine this from the AST without doing things like expanding templates is nasty.)
He doesn't say an infinite set, though:
> Turns out, there exists no algorithm that says “yes” or “no” to the Post Correspondence Problem in finite time, given any set of dominoes as input.
That means any finite set of dominos.
It's similar to the idea behind the halting problem, it's not checking whether an infinitely long program will halt, but whether any possible finite program will halt.
So if you make a C++ program that compiles if the equivalent arbitrary Post Correspondence Problem is solvable, and compiles forever otherwise, you've proven that C++ compilation is not decidable.
Now we can write programs that attempt some sort of clever reasoning to figure out whether or not there is a solution at all. But given any specific program that does that, there is a finite arrangement of dominos such that either the program produces the wrong answer, or cannot possibly finish. In other words, for any algorithm there is a finite problem that cannot be properly decided by that algorithm.
Given an axiom system such as ZFC, we can write a program that searches through all proofs in ZFC for a proof or disproof that a particular case of the Post Correspondence Problem is solvable. This, being an algorithm, has a finite input that it will either produce a wrong answer for (meaning that ZFC contradicts itself) or else will never finish. Whether or not that case has an answer is not decidable within ZFC!
Ideally we want the answer to be "there is no solution" in this case. But if we introduce the axiom that there is a solution, we will never find a contradiction and never be aware of any disturbing conclusion beyond, "That solution must be really, really big." It turns out that, no matter how hard we try, first order logic cannot correctly encode the concept of "finite".
This is what we mean by "undecidable".
So: arguably the grammar is decidable, but to parse C++ you need more than the grammar, you need the full metaprogramming machinery. That is, C++ has ended up in the same state as a language that simply provides Turing-complete macros.
- C++-17 (-20) constexpr is one century in advance in front of rust macro in term of power and what you can do with it. It is not even comparable.
- C++20 compile time execution is currently pretty clean and has nothing to do with this template mess shown here. Definitively not "half baked".
Isn't this where the `typename` keyword comes in? `typename` is required when using a qualified (meaning ::) dependent (it references a template parameter) identifier as a type. My understanding is that uses of types without typename is a common helpful extension but is not strictly conforming.
C++ language lawyers, please check my work...
> The keyword typename must only be used in template declarations and definitions and only in contexts in which dependent names can be used.
The syntax has become so ridiciously complicated, I have developed an involuntary gag relfex every time I read any kind of "modern" C++ code (i.e. heavy use of templates / generics / keywords).
Maybe something you would be interested into: http://dlang.org/.
Do you also object to Lisp Macros?
Over-evolution isn't a good thing.
https://twitter.com/timur_audio/status/1119160309573242880?l...
I can understand having crazy syntax for rare and exotic things. But variable initialization is not one of those things...
It's a disambiguation thing: https://en.wikipedia.org/wiki/Most_vexing_parse
The simple recommendation is to just always use {} when you want to construct an object, see https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines...
Please have a sense of humor.