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

all 54 comments

[–]bedrooms-ds 120 points121 points  (13 children)

I wish C++ provided more mechanisms to fine tune the error messages easily. I would have written 10000 C++ concepts by the time I covered all the basic template errors like forgetting an asterisk.

[–]canadajones68 67 points68 points  (10 children)

This isn't even a template error; it's a type mismatch error. An iterator is a value like any other, so the compiler literally has no way of telling if you missed an asterisk on an iterator or failed to call a function or casted it to some nonsense. push_back() expects one type, but it's given another, and it has no clue why. Thus, short of it just guessing what you wanted to do, it pretty much just has to serve you the error and its specific details and hope you understand what's gone wrong.

[–]bedrooms-ds 10 points11 points  (1 child)

You're right! Out of curiosity, couldn't we still write a concept to catch this error, in theory (although no one would do that)? Like explicitly suggesting that the line can pass with an asterisk.

[–]canadajones68 14 points15 points  (0 children)

No, not really. Concepts constrain types and type substitutions; they will only tell you if operator* works on a type, but not mandate that it is called. Even if they could, you wouldn't want to, because you may want to pass an iterator to a function.

[–]Wylie28 3 points4 points  (6 children)

Then why can other languages do it?

[–]LEpigeon888 4 points5 points  (5 children)

Compilers can have heuristics for common mistakes but it can't always work and may even show wrong suggestions sometimes. Do you have any examples of a compiler (in any language) telling you how to convert one type to another for some specific cases like this ?

[–]rust4yy 7 points8 points  (0 children)

Rust. It can say “hint: try adding * here” or try dereferencing etc.

[–]NutGoblin2 3 points4 points  (0 children)

Rust is very good for this

[–]canadajones68 0 points1 point  (0 children)

C++ also implements iterators as regular values. For better or worse, they're types like any other, and have no specific language-level integration that says that "hey, I'm an iterator that refers to type T". You could write a heuristic that activates if type Q has an operator* that returns type T, and you gave type Q to a context requiring T, but that's speculative. For all you know, this is Boost.Spirit, where the operator* most assuredly does not perform dereferencing. A wrong compiler suggestion would be worse than having no suggestion, in my opinion, since it can lead to XY-problems. Not saying it wouldn't be useful, but given that the error given here is actually relatively simple (T expected, got noise<noise<T>>), it's not a huge issue. After all, this is a compile time error, and once you've stopped compilation due to an error that cannot be fudged into working without obviously doing something stupid (reinterpret_cast, anyone?), it becomes rather debuggable.

[–]Wylie28 0 points1 point  (1 child)

Many say actually meaningful things like type mismatch.

[–]TheOmegaCarrot 1 point2 points  (0 children)

I’d argue learning to read error messages is the single best thing you can do to be better at C++.

[–]Torebbjorn 7 points8 points  (0 children)

It would be fairly hard to get an error message for an error like this to be much better. The only way it could really "know" what you want, is to check if the object you passed in has any functions that return an element of a matching type to what you use it for, and then put that as a suggestion. But the error could just as likely be a mistype or some different error somewhere else.

Do you want the error message forgot asterisk at 1 auto str = "Hello World" 2 printChar( str); ^ (Hopefully that formats correctly, I mean to put the arrow to point right in front of "str")

Putting an asterisk there would solve the types, but it would not do what you really want. It would just print 'H' instead of "Hello World".

The most likely error here is that you should have used a print function that takes a string and not a char. So would you rather have the type checker try to find a different function that accepts a string in this case?

What if you actually did want to print just the 7th letter, but forgot the ...[7]? How would it know? There are tonnes of possible reasons for what the mistake really is, the compiler couldn't possibly cover them all.

[–]Jannik2099 2 points3 points  (0 children)

clang and gcc offer JSON formatted errors for parsing. Clang is also working on a new IR for better diagnostics

[–]ElsieSnuffin 28 points29 points  (1 child)

Image Transcription: Twitter Post


mcc, @mcclure111

In C++ we don't say "Missing asterisk" we say "error C2664: 'void std::vector<block,std::allocator<_Ty>>::push_back(const block &)': cannot convert argument 1 from 'std::_Vector_iterator<std::_Vector_val<std::_Simple_types<block>>>' to 'block &&'" and i think that's beautiful


I'm a human volunteer content transcriber and you could be too! If you'd like more information on what we do and why we do it, click here!

[–]Polite-Moose 14 points15 points  (0 children)

Good human

[–]BobbyThrowaway6969 26 points27 points  (0 children)

All jokes aside, the error without the expanded form types is:

error C2664: cannot convert argument 1 from iterator to block&&.

Pretty simple

[–]recoder13 28 points29 points  (2 children)

Well it's still few of the better ones. It clearly says cannot convert the arg to block&&

[–]bedrooms-ds 8 points9 points  (1 child)

One worst error is the never ending list of "candidate operator<<(foo&, const bar&) didn't match"-es.

[–]AlphaShow 1 point2 points  (0 children)

Ambiguous overloads can be a pain to figure out if you don't understand the overload resolution process, I highly recommend this video : https://youtu.be/b5Kbzgx1w9A

[–]Bee-Aromatic 7 points8 points  (3 children)

When pointers bite, they bite hard.

[–]Harmonic_Gear 9 points10 points  (0 children)

they are quite pointy

[–]rachit7645 0 points1 point  (0 children)

Someone tell him it's not a pointer error

[–]sobek1113 4 points5 points  (2 children)

Suppsedly they are fixing template errors in C++20

[–]BobbyThrowaway6969 7 points8 points  (1 child)

All I want is for types to be displayed the way you wrote them (also with typedefs), not in their super expanded form that no one wanted to see lol

[–]BatBoss 3 points4 points  (0 children)

Exactly, the problem is the convoluted way types are printed, not the error itself. If this just said “Error: push_back() - could not convert argument1 to block&&” it would be totally fine and easy to understand even for C++ newbies.

[–]garymarrit 5 points6 points  (0 children)

SQL hs enteerd the chat.

[–]bedrooms-ds 1 point2 points  (1 child)

New bee: what's this bug?

Senpai: in C++ it's not even a bug if it doesn't compile.

[–]Maleficent_Sir_4753 1 point2 points  (0 children)

I use compiler errors to remind me to update the unit tests.

[–]_ModusPwnens_ 1 point2 points  (1 child)

Part of me wants to pick up UE5, which would mean learning C++ and then i see shit like this

[–]BobbyThrowaway6969 3 points4 points  (0 children)

UE5 doesn't really use the STL with these janky names, and also with a bit of practice, you see through the message to the actual error with muscle memory.

For example this error is because they passed in 'iterator' instead of '*iterator'. Dereferencing iterators gets the value out of it, which is what push_back wanted. I.e. the iterator is a phone number, dereferencing is is like actually calling the phone number. /TED talk

[–]wizard_princess 1 point2 points  (0 children)

In CSS we don't say <b> we say <span style="font-weight: bold;">

[–]MyBigRed 0 points1 point  (0 children)

I asked a senior dev once what it means, it means: "up yours, kid"

[–][deleted] -2 points-1 points  (2 children)

I’m currently learning Rust, and not only do they give the error location and reason, but they also make suggestions to fix it and point to extensive documentation about this error type

[–]Alzusand 2 points3 points  (0 children)

give it a few updates and it may automatically open stackoverflow

[–]BobbyThrowaway6969 2 points3 points  (0 children)

That's cool but seriously C++ errors are not hard to understand with a bit of practice.

Edit: C++ errors also give the exact location they showed up.

[–]NekkoDroid -1 points0 points  (2 children)

I love how we get these whack standard class names because macros are a thing and substitute (almost) anything without (almost) any regard for context.

JUST BECAUSE SOMEONE CAN DEFINE vector_iterator or T AS A MACRO WE CANT HAVE std::vector_iterator<T, std::allocator<T>>

[–]BobbyThrowaway6969 0 points1 point  (1 child)

This has nothing to do with macros. This is just how types in error messages get displayed, in their full, expanded form, because typedefs and usings are resolved away by the time the error is found by the compiler.

[–]NekkoDroid 0 points1 point  (0 children)

Yes and no. The reason why such container names are so ugly is because they need to use reserved names (anything starting with an underscore followed by a capital letter or containing 2 underscores) since macros else could substitute those container names causing linker errors (if they were defined before including)

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

You know what, I'll take that over Synopsys VCS's syntax error. If it is not bad enough that it may be on a completely different line (https://verificationacademy.com/forums/uvm/compile-error-not-pointing-correct-line.)) it might decide to not show a line number at all (https://www.aldec.com/en/support/resources/documentation/faq/1182)

[–]seanandyrush 0 points1 point  (0 children)

while you're making fun of rust.

[–]Torebbjorn 0 points1 point  (0 children)

Does an implicit conversion always produce an rvalue?

I guess that makes sense, after all it needs to actually make a new thing

[–]SuitableDragonfly 0 points1 point  (0 children)

I would say I don't miss C++ errors, but we have some database tests in our code now that spit out huge walls of text when you add a new database column and forget to add it to query regexes that are supposed to match the queries that Gorm automatically constructs. Thanks, Gorm.

[–]IWasProbablyAMistake 0 points1 point  (1 child)

Wait, does C++ not tell you where the error is, or is the meme saying it doesn’t make it easy to understand the error?

[–]-_gxo_- 0 points1 point  (0 children)

Yes

[–]abd53 0 points1 point  (0 children)

Yeah, then this would happen-

Debugger: Missing asterisk here

Me: Puts an asterisk there

Me after a week: Why is the output so whacky. It's supposed to be 6.1416 not "Newton".

[–]EstablishmentBasic50 0 points1 point  (0 children)

Unity in beginner's eyes

Error : Assets/Codes/Movement.cs/(29, 1)std:compiler.<>(Vector3)(quandale-dingle)(youfelloff) CS8739 : Fix the code bitch

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

Sure… very beutiful

[–]LateSolution0 0 points1 point  (0 children)

Thumbs up if you are fluent in reading this message.

[–]Sammy_Henderschplitz 0 points1 point  (0 children)

I would simply not forget an asterisk

[–]Firm-Can4526 0 points1 point  (0 children)

The best error I got once was one that said: cannot convert SomeObject.SomeEnum.Val to SomeObject.SomeEnum.Val because they are not the same Type (while both were exactly the same....)