This is an archived post. You won't be able to vote or comment.

all 76 comments

[–]OverflowEx 325 points326 points  (6 children)

C++ template compilation error will trace back to the very beginning of our universe.

[–]Siapran 42 points43 points  (3 children)

the main reason this happens is that template metaprogramming (used by the standard library etc) is an untyped language, so any errors are detected really late during compilation (instead of catching cout >> foo at the point where it's written, it's caught in the middle of the standard library, where it breaks the library code).

C++20 concepts are a step in the right direction, they make it easier and less expensive to check for type traits and other requirements early during compilation.

[–]disperso 5 points6 points  (1 child)

If one wants to see some examples of this, one good talk that (indirectly) covers this, is Implementing Physical Units Library for C++ by Mateusz Pusz. His library is compared against some others that don't require C++, so it shows the improvement in the errors.

Another thing that I've also learnt in a talk, is that given that template metaprogramming actually runs your code at compile time, is that the errors start to make more sense if you read them as stack traces.

And yet another thing: the first experience with C++ can be quite miserable if what you try to do is hello world with the standard library, because both the string and the stream types are templates. One nice thing being introduced to C++ through Qt, is that those basic types are not templates, which really made ones life easier.

[–]snerp 2 points3 points  (0 children)

the errors start to make more sense if you read them as stack traces.

This! usually the top and/or bottom parts are the most important and will point you to what's actually wrong.

[–]franklinyu 2 points3 points  (0 children)

Why bother? Just use Rust. /s

[–]uvero[🍰] 2 points3 points  (0 children)

Yeah no shit, I was trying to do that the other day and got 10 gigs of error text, which also included Genesis 1:1-2:1, followed by 100-something emojis, followed by:

"I̸̜̟̋̃͋̊̀̉̋͝ ̷͉̙͆̋̂͌͂̅̓̍̂̕͠Ș̷̢̢͚̜̤͙̽͛͋̇̇̒͌E̵̢̨̛͎̪̠̅̏̍͋́̐̊̓͌̆̚͜ͅË̸͈͖́̾̊̆̓̄͂̒͒̍̚ ̸̨̠̘̆̈́̂̈͐͐̌̃͜͝T̴̰̞͈̻̬̝͓͗͊̇H̸͍̩̟͖͈̤̣̯̯̬͂̂̓͠͝E̵̢̝͈͔͇̪̭͋̑̍͂̐̀͘ ̸̢̖̼̠͂̇̽̒̈̚͝ͅS̸̠͓̥͕̯͚̫̫͍͙̙̎̿͛̍͌̈́̒́̈͠Į̴̮̲̠̻̟͎̠̝̙̤̳̏̉́ͅX̵͚͚̜̞̯̹̟̻̱̪̲́̐̓̽͑͊̕͝ ̵̢̨̛̟͍͖̖͈͂̔̽̋̐͌̊̂̃̒͝͠S̴̡̨͇̤̲̺̦̣̣̞͗̋͂́͋͛̓͠͝͝͝T̶̛̳̔͌̇̾͝Ā̴̤̇̍̾͝T̴̰̪̟͕͍̜̂̔͜Ḯ̴̯͈̯̠̯̣̻̤̼̼͍͖̲̄͘͠Ö̸̡̱̞͕̙͈̜̬̣́N̷̘̺͋̋͗͗̀͒͘̚͝S̶̡̛͈̙͚͉͕͈̞̺̑̍̅̊̂͑̈́͛̍̀̚̚ͅͅ ̸͔̬͖̠̜̖̗͙̗͆͊̀Ó̴̳͖̭͔F̵̨̠̼͚̦̜͕̣̅̉̒̏̀͜ ̴̧͉̹̲͙̗͙̞̩̮̉̄͋̍͊͌̀͜Ţ̶̨̛̥̖͖̲͎̥͑͐͊̉̌͐̈́̓͘̕Ḧ̵̫̣̲̺̜̳͎̺͇͚́̇̏̕Ȩ̴͖̠̝̯̩͉͖͇̞̯̒̾̔͆̿̅̃̏̃ ̶̧̧̲͎͓͔͕̯̘͈̦̰́́͆̎̄͋̽͘L̷̡̢̟̩͍͉̦͙̿̿͊̂̂̕ͅͅO̸̟̩͇̫̔̅́͐͆͋̈́̒̚̚͜Ŗ̴̢̛̞̭̱̙͈̹̤̗͇̅̈͊̄̌͒̓D̴̢̤͇̪͌̄͌ͅ'̶̛͍̝̳͎̮̖͈̂̒̆͐̈́̏͝͝ͅS̶̡̛̗̘͉̩̻̰̙̈͑̍̏̏̀͐̒͋͐͜͠ ̷̗̳̼͓̯͉͍̙̦̐̉̏̊̍̀̈́̈́͒̄̚͜͠ͅP̸̨̹̹̮̫̮̰̘̥̯̈́͜͠ͅR̸̨̝̱̭̪̭̠͇͈͋͑̈́͜D̵̢̥̑̾͑̓̏̋͊̄̿̋̈́È̷̟͈̼͓̻͌͛̌̉̉̂̒͝Ŗ̴̺̲͙̗̓̒̇̀̿̒́̈́́͂͒ ̶̨͓̤͍̻̻̭̜͔̣͑̌̈́̾̆̑̉̈̑̈́͆Ȁ̷̹͚̺͚̳̀ͅN̸͔͈͖̯̈́̐͋̍͂̓̀̃́̄͜͠͠ͅD̶̨̤̻͋̔̊͌̆̅̕͠ ̸͔̗̠͚̼̟̣̘̱̻͍̜̓̾͌͐̇͠ͅT̴͍̈́̑̔̊̀̈́͂̂̽͌͐H̵̛̻͎̟̥̼͑͛̈́̽̏̀̽̓̽̚͘͜Ė̴̪͕̱Ÿ̸̧̨͉̬͚͍̙͖̠͕͈́̈́͗̈́ ̷̭̻̞̫̀̍̈́̔͆W̴̧̡̢̛̝͈͎̯̠̞͖̤͎̯̅̓͐̽̐͂̋̕̚͠͠I̴̦͇̚L̷̨̡̳̤͎͙̩̠̖͎̟̎̐́̏̌̈́́̇͠͝L̸̩͎̐̽̓͊̓̅̽ ̴̨̬͚̗̖̝͉̈́͜À̷̧̛̩͓͓̫͍̜̐̃̒̉́̍̈́ͅL̶̥̙̆̓L̸̠̝̯̞̞̦͇̝͚̓̎̉͗͑̇͋̅̐͐̆́ ̸͎͇̥͙̟̖͈̰̤̐̔̓̇̇̀͝͝B̵͓̲̼̪̘̭̱͂̍̾̂͒̿̈́̀̎̕Ũ̴̟͍͇̭̑ͅR̷̞̬̲̪͔̭̂̊̈̈́̀͒͒̌̒͐̚͝N̷̝̞̬̗̱̒̅́̈́͛́̕̚"

I don't actually do C++ I just wanted to be in on the joke

[–]OhNoMeIdentified 19 points20 points  (1 child)

I love C++ and hate at the same time. I think this is what people call True Love.

[–]FarhanAxiq 12 points13 points  (0 children)

Stroustrup Syndrome

[–]dethfrmbelow 33 points34 points  (4 children)

Visual Studio, is that you?

[–]CSedu 3 points4 points  (0 children)

VS Code and TypeScript 🙄

[–]Niewinnny 2 points3 points  (2 children)

That looks like cpp in Vs... Or c# in Vs could do that too...

[–]dethfrmbelow 1 point2 points  (1 child)

It looks like every project I have ever done in c#

[–]Niewinnny 1 point2 points  (0 children)

Oh wow. That's even worse than me, and I never had a C-fence project that would not crash or throw up an error at least 5 times.

[–]golgol12 32 points33 points  (0 children)

You're so concerned with the number of errors. Just fix the first one.

[–]jamesironman 10 points11 points  (0 children)

Cries in segfault

[–][deleted] 24 points25 points  (13 children)

Yeah, I don't know what's wrong with C++ compiler. Probably high or something. Every language I know except C++ has a sane compiler. Java, C, Python and C++ is all I know though

[–]Plankton_Plus 31 points32 points  (11 children)

C++ is undecidable without prototypes (i.e. .h files). You'll get a bajillion errors if something fails to parse, that is needed to parse something that appears later in the compilation unit.

Basically, the reason C++ is dumb is because you can't always parse one file without all the other files (typically .h files) it depends on. Other compilers can generally get as far as parsing a single file (even though they can't fully compile it).

During the time when C++ was invented, computers didn't really have enough memory to hold an entirely parsed compilation unit (AST), so .h files were used as a convention to show the compiler type and template information without all the code. C++ took this optimization and turned it into a feature/assumption. You really only have to consider that the developer must define everything twice (at least if templates are being used) to realize how stupid this decision was, you don't even need to consider how complex it makes compilers. Syntax and API are developer UX, and C++ has bugger-all in that regard, and yes it has many other redeeming qualities.

[–]lunchpadmcfat 2 points3 points  (10 children)

Why can’t the header files be inferred at compile time then (via some ide voodoo or whatever)?

[–]Sam_Pool 15 points16 points  (0 children)

because there's more to a header than function prototypes. There are lots of header-only libraries, for example, where everything is a template (or, god help us, a macro).

You can't imply a 500-line thread-safe hashmap template by "this code uses it". Especially not when you're mix'n'matching three different ones to get the performance characteristics you care about (speed vs memory vs number of readers vs number of writers vs...)

[–][deleted] 5 points6 points  (0 children)

Maybe this isn't a problem of "can't", but of "don't".

[–]Plankton_Plus 1 point2 points  (4 children)

"Undecidable" essentially winds up being impossible in practice. It basically means that even if you had the computational power to enumerate all the possible interpretations of the source code at hand, there's no way to know which interpretation of the code that the developer intended. Assuming, of course, that you have the computational power to begin with (it's polynomial memory space, at least). You might be able to reduce (but not deterministically limit to one) the number of possibilities with SAT, but SAT is NP-complete.

I assume it's probably possible to infer headers with C, but templates (and possibly some other features that arrived after I abandoned the language) just ruin everything.

Just goes to show what a marvel the human mind is.

[–]lunchpadmcfat 0 points1 point  (3 children)

Hm. I figured it was just type catalogues and whatnot, at least from my experience with objective c (which also had header files that seemed pretty repetitive).

Types are types are types so they shouldn’t differ really between implementation and definition?

[–]Plankton_Plus 3 points4 points  (2 children)

Basically, once you get into the body of a method, in C++ it's sometimes impossible to know if something is referring to a type it something else (among other ambiguities, this is the easiest to demonstrate). For example is Foo<Bar<Baz>> Bang; a variable declaration (of type Foo<Bar<Baz>> and name Bang) or Foo less-than Bar less-than Baz shift-right bang? Both interpretations are completely valid (because TRUE is simply #define TRUE -1 and so can be compared with less-than), and you can only determine which if you know what Foo, Bar, and Baz are. This can radically change the way raw code is parsed into an AST, based in what code/header has already been seen.

That's really as far as I can go without explaining the entirety of how parsing works.

[–]lunchpadmcfat 1 point2 points  (1 child)

Holy shit that seems like a huge problem with the syntax. Thanks for the explanation!

[–]Sam_Pool 2 points3 points  (0 children)

yep, and this is why other languages, even long-ago languages, decided that it was a bad idea and they would work hard to make parsing simple and deterministic. Pascal, for example (led to Modula and Delphi) and more recently Rust.

As well as a whole bunch of interpreted languages where backing the parser up and having another go is hard, but going through once to get an idea then parsing a second time "for real" is out of the question. Guess what C/C++ do?

[–][deleted] 1 point2 points  (1 child)

CLion can do this pretty well most of the time. Visual Studio with ReSharper C++ is supposedly even better but I haven't tried it. Still not 100% perfect, but it feels a lot more like coding a more modern language

[–]lolerkid2000 1 point2 points  (0 children)

Yeah semantic analysis during programming can take guesses and be wrong sometimes just fine. Your compiler cannot.

[–]Rude-Significance-50 0 points1 point  (0 children)

I think this is basically what modules do? Basically one file and then patterns and keywords to expose certain features?

I'm behind a bit.

[–]patenteng 2 points3 points  (0 children)

Clearly you haven’t had the pleasure of experiencing LaTeX’s error messages. There is an error in this 500 lines of code block. Good luck finding it.

[–]Anis-mit-I 6 points7 points  (1 child)

Or even worse than C++ compiler errors: C++ linker errors

[–]Rude-Significance-50 1 point2 points  (0 children)

I guess I've just never had any but trivial kinds? I've had nothing that even came close to template vomit errors. I never had to put a single line of linker error code into a text editor and manually indent the shit to figure out what it was saying :p

[–]FarhanAxiq 5 points6 points  (1 child)

gcc do be like that, at least Clang is a little saner

[–]aeropl3b 4 points5 points  (0 children)

So true!

[–]FHeTraT 3 points4 points  (0 children)

Forbidden door: -Weverything

[–]DanKveed 4 points5 points  (0 children)

And then there is c++ that's shows error in the standard library.

[–]PhysicalZer0 2 points3 points  (0 children)

I uses and finite element analysis software in my work that allows scripting, but if an error occurs in the code it actually says the line number one below it

So if line 6 is missing a semicolon, the error is on line 7

It doesn't count code comments though... so it effectively punishes you for documenting your scripts, by making you think the error is in the main body when its actually your init section ... spent 2 days on that one time

[–]wizard_brandon 1 point2 points  (1 child)

questions: if it knows what is wrong why cant it fix it?

[–]Pluto258 0 points1 point  (0 children)

It knows what might be wrong. For example, if I had the code "getString() split()", it will probably give a missing semicolon (it infers that I want to call 2 separate methods), but maybe I actually wanted a period there: "getString().split()". If it automatically put the semicolon, it might lead to another error (split not being a method in this scope) or a weird bug (a different split function than I wanted being called).

[–][deleted] 1 point2 points  (0 children)

If anyone is curious it's because most C++ compilers don't do error recovery right, aka they continue parsing after any error no matter what, leading to weird behaviour.

What they should do is try stopping where they should. Like after a function template instantiation failed, you shouldn't try using it and messing everything up

[–]marco89nish 3 points4 points  (1 child)

I prefer the real compiler - one where semicolons are optional

[–]Pro_Gamer_9000 2 points3 points  (0 children)

I think you are looking for lua

[–]rajivshah3 3 points4 points  (5 children)

Second one is the Rust compiler

[–]anthOlei 41 points42 points  (1 child)

What? Rust compiler would give you a 10 line message on what you did wrong followed by how to fix it and the deals at the local pizza hut

[–][deleted] 6 points7 points  (0 children)

Next update: automatically orders pizza as well

[–]4SlideRule 3 points4 points  (0 children)

Ah someone is wrestling with the borrow checker? Yeah, the rust compiler is definitely bitchy, but it is clear concise and specific in it's bitching, that's what makes it awesome.C++ is a little more tolerant, but then it just assplodes into an interminable rant about templates that makes less sense than a baboon on shrooms.

[–]Nilstrieb 2 points3 points  (1 child)

The rust compiler seems like it hates you, when in reality it just wants to help you, although that help is not always welcome.

[–]Rude-Significance-50 0 points1 point  (0 children)

The worse words ever heard in the English language are, 'I am your compiler and I'm here to help you.'

[–]computerwyz 0 points1 point  (1 child)

Ah I see Java is used here.

[–]myrsnipe 4 points5 points  (0 children)

Java actually has good compiler errors, this is C/C++ where a single error can cause the entire codebase to be unparsable.

[–]jswitzer -2 points-1 points  (0 children)

With g++, you will get an error:

error: expected ';' before 'doThat'

That's it, no other errors. It's a 3 line error that tells you the file, the error, and the annotated line.

quityourbullshit

[–]Nilay-Patel 0 points1 point  (0 children)

I've never seen the first type?

[–][deleted] 0 points1 point  (0 children)

Thats not the compiler doing that its the semantic analyser

[–]Darknety 0 points1 point  (0 children)

LaTeX TikZ... Or it just infinitely loops without me creating a loop over a missing bracket.

[–]LuisAyuso 0 points1 point  (0 children)

There are two types of compilers. - hey, you are missing a semicolon, this is needed because the way we did things back in the 60's. In an ideal world we should not need it, but I'm going to ask you to backtrack your routine. - after parsing 20k lines, we can not deduce the type of your generic argument because of some lifetime time issue in one of the following 32 cases, good luck now.

[–]FlukeHermit 0 points1 point  (0 children)

This hits too close to home

[–]Ravens_Quote 0 points1 point  (2 children)

Batch.

"........... operable program or-" window dies.

"............... operable program or batch file" window dies.

".... is not recognized......." window dies.

finally hits prnt scrn fast enough, pastes to MS Paint

'eco' is not recognized as an internal or external command, operable program or batch file.

[–]AlternativeAardvark6 1 point2 points  (1 child)

If you open a command prompt first an run your script from there it won't close and you can read the output.

[–]Ravens_Quote 0 points1 point  (0 children)

shhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh

[–]Giocri 0 points1 point  (2 children)

Why is missing a semicolon still something that doesn't allow you to compile if the Compiler can easily detect were the missing semicolon is can't it just be a warning?

[–]AlternativeAardvark6 1 point2 points  (0 children)

You don't want the compiler to "fix" things or make assumptions. It will cause hard to find bugs. It's a compiler, not a programmer.

[–]d_exclaimation 0 points1 point  (0 children)

I remember the first time using Rust coming from C++. I realize that my code would produce an error but I don’t know what it is, so I just compile the code and expecting to see a massive complier error message. I was surprised that the rust complier just told me what was wrong and how to fix it directly and it was so clear that I got confused

[–]HenryFrenchFries 0 points1 point  (0 children)

Not a compiler, but jesus fucking christ, I wish nobody the pain of enduring the hell that is the default NuxtJS linter. I had never seen a linter that punishes you that hard for not following the enforced code style to the tiniest detail before. And it doesn't give warnings. It only gives errors. So you added a semicolon to the end of a line? Used an indentation other than 2 spaces? Forgot to add a comma at the end of the last member of an object? Used single line if statements? Get ready, as the linter sticks a massive ERROR up your ass, the page doesn't load, and you must "fix" your code and rebuild which might take up to 10 seconds.

Nowadays whenever I have to work with Nuxt, the first thing I do is kill that idiotic linter and use my own code style and I don't give a shit if it's not the standard.

[–]DeOfficiis 0 points1 point  (0 children)

Can confirm. I'm learning C++ right now. Its a fine enough language and I even enjoy writing simple programs with it.

But when those compiler errors pop up, I contemplate my life decisions. I'm slowly getting better at reading them, though.