6 ms·
Some of these absolutely makes sense and are justified; others...are actually sane to have in c++. For instance: > int foo(void)/int foo() In c, int foo() me
by earenndil 7y ago
Some of these absolutely makes sense and are justified; others...are actually sane to have in c++. For instance:
> int foo(void)/int foo()
In c, int foo() means that foo takes any number of args; c++ rightfully realised that that was stupid and removed that feature, which means int foo() can now be used to mean foo takes no args. Also, int foo(void) is illegal in c++.
Varargs in c are a complete pita to use, not to mention they literally do something different from function overloading/default args.
Constexpr is much nicer and safer to use than a macro.
Using malloc and calloc to make class instances means you can have unconstructed objects, which is a Bad Thing, and while introducing a new operator to do that is not necessarily the best way to handle that, it's a perfectly valid way of doing so.
Libc random is just garbage, and libc++ random is actually decent.
setjmp/longjmp are more complicated to use than try/catch, and don't have all the same functionality.
<iostream> functions are type aware (although really they should have used fmt).
I'm no c++ apologist (it's an awful language), but this listicle is just...not great.
- wnoise 7y ago> Also, int foo(void) is illegal in c++. Uh, citation needed. It would make compatibility with C libraries harder for no good reason. I believe it is valid as both declaration and definition. Both g++ and clang++ accept it without even a warning.
- hermitdev 7y agoI dont know offhand if it's illegal, but it's certainly unnecessarily verbose. Likewise, every compiler I've used accepts it, but it's unnecessary. Also, maybe a difference in behavior if code is in 'extern "C"' or not. I'm not sure. I rarely directly deal with C libs and havent been doing C++ for about 6 months now.
- harry8 7y agoUnnecessary is a question of taste, right? foo(void) seems less likely to cause confusion to anyone who hasn't got that C vs C++ distinction uppermost in their mind - I didn't. Nobody knows C++, we all know a subset of it and a smaller subset than we think we do and actually use, despite pretty constant study! Anything you do that makes a reader less likely to be confused, to make it less likely that they will or should break their flow by looking up the rule, is a good thing (tm). C++ suffers from "macho coding" styles and ethos quite badly. "I /believe/ I understand this subtlety at this moment so anyone who doesn't is stupid." Even when we didn't understand it ourselves just last week we forget it(!) We fool ourselves into thinking anyone who hasn't got at least a decade of hacking C++ every day is unworthy of reading our code, possibly pretending that 6 months can attain that level of oneness with changing standards. I try to use popular and safer features without thinking about it and if I want to use something slightly less popular when there is a choice, I ask "what problem am I solving? Is lowering readability a price I'm happy to pay here?" Before charging ahead with it. I probably classify some of the latter as the former due to over-familiarity. The ideal C++ code is rapidly readable and understandable without extremely taxing effort by a smart highschool student with 2-3 months of C++ experience. (Note the use of the word ideal in that sentence). s/C++/any language/ is also applicable. Other than following the style of the project you're working on is there any reason to use a reference ever over say a const pointer? Or a const pointer to a const object? The syntax then makes it clear you're not dealing with a pass-by-value copy. Maybe in another world everything would be const by default and have to be marked mutable then references might go away - but C++ couldn't do that and compile C which explains /some/ of the tension inside the language between various C++ features. Shame they didn't make references const by default if they had to introduce them. And member functions defaulting to const and explicit constructors by default. Const construction by default etc. There was an opportunity lost a long time ago to tighten up everything that isn't legal C as far as possible with the programmer having the option with an additional keyword.
- hermitdev 7y agoI largely agree with what you say, but can you elaborate on what you mean by "macho coding" styles? I'm guessing youre referring to when one deigns venture into template metaprogramming. TMP is an area with 2 decades of experience, I can basically only do it with a copy of the standard and/or relevant reference material handy. Although I'd consider my C++ knowledge in the 95th percentile or so, I probably know less than 20% of the std lib well. I've read most of the +1200 pages of the C++11 spec, but ive not kept up to date since, sadly, because its no longer my daily language.
- harry8 7y agoWhat I mean is anything that is showing off, has a lack of humility and implicitly disparages others in a way that is totally unneeded while producing lower-quality, less-maintainable, less robust code. Being clever for the sake of appearing clever. That kind of thing. if(condition) I_am_tough_so_I_do_not_brace(); The un-braced block is a classic "macho" pose in code. leaving out a '{' and a '}', two characters, has no benefit in any way, shape or form. It is decrying "I will never make a mistake with this loose razor blade if you do maintaining it is because you suck" There is literally no reason to do it ever, under any circumstances. Yet I have, and we do. We can change. Now watch the arguments presented when you bring un-braced blocks up. They're insanely ridiculous. (vertical space, need static analysis, etc.) If you were betting your retirement savings on no bug in the line of code now or in the future, you'd be very nervous about it sure. And then you would brace it. Unbraced blocks are a minor thing that mostly don't matter. I wouldn't fight too hard over it. It's just that it's so very, very clear that one way is bugs for zero benefit while the other isn't. Meh. So here's Bjarne being "Uber-Macho" to the delight of the conference crowd. Note the quote: "I think I understand what you're saying and I think you happen to be wrong." (crowd whoops in glee). https://youtu.be/OB-bdWKwXsU?t=4141 https://youtu.be/OB-bdWKwXsU?t=4141 This is a pretty ugly way of saying "I disagree and this is why..." But the crowd loves it. That attitude gets into our code. "Macho coding" is the best descriptive name I can manage. Maybe there's a better one? (Note I agree with the content of Bjarne says, I just think he's being an asshole about it, why do that? https://www.urbandictionary.com/define.php?term=Waltersobchakeit https://www.urbandictionary.com/define.php?term=Waltersobcha... )
- kllrnohj 7y agoI think the problem is mostly in the tone of the opening paragraph and less in the list itself. By prefixing this with "Don’t automatically assume that C++’s situation is desirable, necessary, or inevitable." It seems to be trying to frame this as C++ having bad duplication. But many of the things listed are not actually strict duplicates at all - like pointers vs. references, since references cannot be null (yeah yeah you can force it but 'int& foo = nullptr;' doesn't compile, either). Which if you then read the explanations at the bottom tend to cover in a fairly non-biased way.
- skookumchuck 7y ago> references cannot be null void test() { int* p = 0; int& r = *p; } compiles without complaint.
- hermitdev 7y agoI've gotten into arguments about this in the past. As you've shown, references can be null, but theyre not supposed to be and are assumed nearly universally to not be. The argument comes down to when the undefined behavior occurs: is it at the deference to create the reference, or is it on the first memory access using the reference? The language pedants will say the former, but in practice, it's the latter. In practice, you'll likely be able to invoke a member function on a null pointer or reference, as long as that member doesn't directly or indirectly access data members, or virtual functions of the type. Obligatory, I dont recommend doing this or relying upon this behavior, it's just behavior I've seen in my 2 decades of debugging C++.
- kllrnohj 7y agoIt's mostly important in the context of codifying nullability. If a function returns a reference it's part of the contract that it doesn't return null. Similarly, if a parameter is a reference it's part of the contract that you can't pass it null. It doesn't mean a method that takes or returns a pointer must allow null as a valid value, of course, Optional<> is better for that. But standards-enforced non-null is a very practically useful aspect of references that differ them from pointers.
- chrisseaton 7y ago> Also, int foo(void) is illegal in c++. What makes you think that? I'm looking at C++ 17, 11.3.5 (4). > A parameter list consisting of a single unnamed parameter of non-dependent type void is equivalent to an empty parameter list. What are you looking at?
- earenndil 7y agoAh, my mistake. Still, though, it's unidiomatic and rarely (if ever) used.
- whyever 7y ago> libc++ random is actually decent. I disagree. It does not include a contemporary RNG, and seeding the only decent one correctly is ridiculously difficult.
- earenndil 7y agoAfaik it uses mt19937? While not as good as it could be; something like pcg would probably be better, that's still very adequate. As for seeding it's pretty easy. It is stupid boilerplate that should be in the stdlib, but it's not difficult. You read from /dev/urandom if on unix, or use cryptgetrandom on windows, xor with time and pid if you really want to, and that's it.