15 ms·
Why C++ Sails When the Vasa Sank [pdf]
- Moral_ 12y agoWhy do people insist on linking to slideshare? http://files.meetup.com/1455470/Why%20C%2B%2B%20Sails%20When%20the%20Vasa%20Sank.pdf http://files.meetup.com/1455470/Why%20C%2B%2B%20Sails%20When...
- dang 12y agoThanks. We changed to that from http://www.slideshare.net/yandex/why-c-sails-when-the-vasa-sank http://www.slideshare.net/yandex/why-c-sails-when-the-vasa-s....
- thrownaway2424 12y agoauto y = std::move(x); Is this good code? How do you review it? What's the type of y? Usually I would ask for at least one type statement per line. For example this seems ok to me, because the type is on the left. auto* x = new Foo(); But this doesn't seem ok: auto y = std::move(x);
- fleitz 12y agoThe types are immaterial to the operation, the important thing is the move, not the type line noise.
- octo_t 12y agowhat about in the case of something like: auto it = std::find(vec.begin(), vec.end(), value);
- thrownaway2424 12y agoThat doesn't bother me because std::find returns an iterator, and nobody wants to look at long STL iterator type names. But if the next thing were this: auto foo = *it; ... I would be sad.
- RogerL 12y agoAre you sad because of the auto, or the terrible variable names? auto gps_position = *saved_position; I can think of cases where I'd want to see the type of auto, but not often.
- SamReidHughes 12y agoThere are a ton of times in C++ or any language where you want the type. If having the type makes the code more readable, you should have it.
- RogerL 12y agoThis is what everyone is saying. The only question is whether to ever use auto in non-generic code. I think it is unarguable that if you can write foo(goo()) in a clean way you can equally use auto. And if you can't do the former, you probably can't do the latter. Balance, proportion, judgment, and code reviews are how you get great code, not 'never' and 'always' rules (which your comment makes clear you agree with).
- AlisdairO 12y agoOne of the nice things about explicit types is that you can make sense of the code even when the person who wrote it wasn't the best at variable naming. I tend to distrust relying on convention. That said, presumably one solution for such an issue is that have IDEs that can easily tell you what the type of an auto variable is.
- maxlybbert 12y agoWhy? You know foo has the type of "whatever 'it' dereferences to." Why would spelling it out be an improvement? Would your opinion change in a templated function where the type is, itself, a placeholder (e.g., "typename T")? What if "it" were originally an unsigned int* but a refactoring changed that to a long*? Would you prefer the programmer hunt down all cases where "it" is dereferenced to change the type of the result, or would you prefer the programmer use "auto" to begin with?
- Scorponok 12y agoYou should only really use "auto" when the type is clear (like in your example #2). If it's not clear, you should probably specify the type so that it's more obvious what's going on. #1 and 3 are probably fine if x is defined right above y, but maybe not if they're at the bottom of a long function or similar.
- Iftheshoefits 12y agoLike anything else in a language in which the syntax and other features permit writing correct code that is difficult to maintain or decipher, your objection has to be handled by a human being (or well-designed analysis tool) at the "meta" level (e.g. by code style guidelines/policies). I agree "auto y = std::move(x)" is (likely) poor coding practice. I only use "auto" basically as a shorthand (e.g. instead of writing "hand_crampingly_long_container_iterator_type v = std::fn(c.begin(), ....)). I have mixed feelings about "polluting" the namespace with "useless" typedefs and similar aliases versus using "auto". The former leads to very explicit code, but lots of extra "overhead." On the other hand, "auto" is much more powerful than a convenient in-place alias as I've described, and I've rarely found myself in the position of looking at code and having to truly ponder over the type of an "auto" variable. On the other other hand, seeing a lot of either may indicate something else about the code and whether it ought to have a design review. It's (somewhat) subjective.
- RogerL 12y agoDo you allow this to pass code review (ignoring the bad name 'foo')? foo (A*x); 'A * x' creates a temporary with no documented type, but the conceit here is that we don't care. They could be ints, floats, matrices - any data type that implements '*'. By and large that is fine. Here you are just moving x to y. What is the type of y? the same type as x, which supposedly didn't cause you heartache throughout the rest of the function. Stroustrup gave an interesting talk this year about how, everytime he introduced a new feature, people complained that it was not clear and asked for very verbose syntax. Instead of foo<T>, we get template<typename T> foo<T>(T, well, you get the idea. Now everyone is familar with templates and loath the verboseness. Back to auto, it allows for 'generic' programming. Do you object to templated functions? template<class T> T add (T a, T b) { return a + b; } That seems really clear to me, as is the auto version: auto add (auto a, auto b) { return a + b; } If that is clear, why is auto x = a + b; unclear? I can certainly come up with counterexamples where it isn't clear, but by and large I love auto, and use it all the time. (counterexample: we care about the type of x because we need to cast to a 16-bit int because it is going to be use to communicate with hardware).
- plorkyeran 12y ago> we care about the type of x because we need to cast to a 16-bit int because it is going to be use to communicate with hardware IMO you should still use auto there and use a static_cast<int16_t> on the RHS to make it clear to the reader that you're deliberately converting it.
- RogerL 12y agoYou're right.
- yongjik 12y agoProblem arises when we find "y" deep in a function, searches for its definition, and encounters "auto y = std::move(x);". Now we have to know the type of x, and if x is defined similarly, up the chain. Not fun. foo(A * x) doesn't pose similar problem. On the other hand, if I write auto bar = foo(A*x); Then we can have the same problem (esp. if foo is a templated function).
- maxlybbert 12y agoWhile C++ programmers are still getting used to type inference, it's not really a new concept. It's been in other languages for decades. Personally, I avoided type inference in C# for a long time. But I never ran into a bug caused by type inference. While C#'s (and C++'s) type system isn't as advanced as Haskell's, if you screw up the types you generally get a compiler error. If "auto y = std::move(x)" compiles, then why do you care what type y is? You know it's the same type as x, and you can do anything with y that you could have done with x. There's really nothing to fear.
- millstone 12y agoConsider this simple code to swap the first two items of a vector: vector<T> foo = ... auto tmp = foo[0]; foo[0] = foo[1]; foo[1] = tmp; When T is int, it swaps as expected. But when T is bool, instead of swapping, it copies the second item over the first, with nary a warning. And I'll wager you could stare at that code all day without spotting the bug. So yes, be afraid.
- Dylan16807 12y agoI object to calling vector<bool> a vector. I'm afraid of it, not of auto.
- detrino 12y agoThis is a contrived example. Not only is vector<bool> the real problem, but this is a standout terrible way to swap elements, especially in generic code.
- millstone 12y agoYou have to admit, it's hilarious that the most natural swap implementation you could possibly write (and the one used in C++03) is now "standout terrible." It's not wrong to point that out, but it is wrong to assign blame to the hapless programmer instead of the language. And even if we make it not-generic, and add some C++11: std::vector<bool> foo = ...; auto tmp = std::move(foo[0]); foo[0] = std::move(foo[1]); foo[1] = std::move(tmp); We've fixed nothing. The problem remains! (It works if you use std::swap, I think because whatever type tmp resolves to happens to overload std::swap to do the right thing.) So why is vector<bool> the "real problem?" It's because its operator[] doesn't return a bool&, but instead some type "convertible to bool," that may do lots of other stuff too. But the standard is chock-full of language like that. For example, with iterators: `str.begin() != str.end()` Is that a bool? `str.begin()[2]`. Is that a char? The standard doesn't require either. Care to roll the dice by assigning one to auto? Type inference works well in other languages, but it is more dangerous in C++ due to the risk of implicit conversions. C++ does so much stuff for you under the hood that it can be quite hard to figure out what is really going on, and auto only makes that problem worse. Use with caution.
- 10098 12y agoI think it depends on context, I like using auto when the type is clear from the surrounding 5-7 lines of code or if it's for some nested-container-iterator stuff. The rule of thumb is, if the context doesn't provide enough information about types to deduce what the inferred type for `auto' will be after a quick glance, then don't use auto.
- wmkn 12y agoScott Meyers (the author of this presentation) makes a pretty good case in the following presentation: http://vimeo.com/97318797 http://vimeo.com/97318797 Unfortunately the slides are not online. But his presentation starts with a case of why 'auto' should often be preferred to explicit type declarations.
- EpicEng 12y ago"For example this seems ok to me, because the type is on the left" auto* x = new Foo(); Are you only referring to the fact that the type is noted at least once on that line? I ask because that would not pass my code review at all 99% of the time (manually allocating memory that way.) As for something like auto x = std::move(y); I couldn't say it is bad without seeing the context around it. Is it a small function? Is it obvious what y is? Looks fine to me in most cases.
- TheSoftwareGuy 12y agodo you NEVER allow dynamically allocated memory? or am I misunderstanding you?
- Nursie 12y agoIn modern c++ you can get away without it by using a combination of RAII and the various shared pointer and container features. It's an odd mental leap for this old C hack, but it works quite well when you get into it. Bonus - no 'free' or 'delete' necessary.
- TheSoftwareGuy 12y agoPlease correct me if I am wrong, but RAII isn't flexible enough to allow for lazy initialization. the various STL pointer types (std::shared_ptr etc..) are great, but they do incur overhead, and sometimes that is not acceptable in e.g. embedded systems.
- cottonseed 12y agoI think he means it should read something like: auto x = std::make_unique<Foo>(); Unless you're implementing an allocation policy, you shouldn't be calling new and delete directly.
- EpicEng 12y agoThere are very few instances in which manually managing memory in C++ is justified. When you have `unique_ptr`, `shared_ptr`, and all sorts of container classes, it simply doesn't come up in most cases. If you see operator new being used you should be suspicious.
- ingve 12y agoThe video: http://tech.yandex.ru/events/cpp-party/june-msk/talks/1954/ http://tech.yandex.ru/events/cpp-party/june-msk/talks/1954/
- angersock 12y agoI've never seen footage of Meyers before...He kind of reminds me of the Tall Man from the Phantasm movies. I guess C++ will do that to you. :)
- 72deluxe 12y agoI always thing his prog-rock 70s haircut makes him look like one of Robin Hood's merry men or a medieval archer. Not that this is a bad thing.
- fn 12y agoThanks for the link to the video. Always been a fan of Meyers but have never been a talk of his.
- cacainmycafe 12y agoI like C++ because I only pay for what I use in the language. Very little overhead or additional baggage to slow or weigh things down, unless, I elect to include the extra luggage. The recent updates - C++11, C++14 and the drafts for C++17 are also very welcome. When you need performant, deterministic, portable and testable code, you go for C++.
- heinrich5991 12y agoThe new Rust language by Mozilla makes similar promises, * only pay for what you use * memory safety * testability * portability (They even got a standard testing module.) EDIT: How do you make lists with Hacker News markup?
- SamReidHughes 12y ago> How do you make lists with Hacker News markup? You just made one.
- loup-vaillant 12y agoKinda. It would be nice to have a richer markup support. We always cite one another, provide links, and enumerate things. Supporting a subset of Markdown (or anything like it) would be very welcome.
- freyrs3 12y agoConceptually they are similar, though it's always important to note that C++ has several man-centuries worth of compiler work. Rust may become stable and efficient enough to replace some existing C++, but at the moment it's most certainly not as mature as the existing C++ ecosystem.
- pornel 12y agoRust uses LLVM, so it benefits from the same optimizer as clang. The front-end is less mature of course, but also Rust is less complex, so may not need man-centuries of work to be parsed properly ;) Currently Rust doesn't outperform C++ partly because LLVM is optimized for the C subset (can't take advantage of extra aliasing/immutability information Rust has), but given that Apple is now betting on (quite similar) Swift I expect LLVM to rapidly improve in this area.
- AnimalMuppet 12y agoTo me, the key line was "Most of the complexity of C++ is hidden from most of the users most of the time." The complexity is there. Trying to understand the whole language at a language-lawyer level is mind-boggling. Trying to write libraries that make proper use of the goodies is very hard. But using C++ isn't so bad, as long as you don't try to use every aspect of it. Just use the parts you need to be able to do what you're really trying to do. You don't have to pay for what you don't use. That's good enough for a huge number of programmers in a wide variety of contexts. There's a lot of haters that can point out a huge number of flaws. But here's the thing: Most of them, I never run into. I don't care if the move syntax is confusing; I don't use it. Maybe I never will. If I have to, then I'll care about how good or bad the syntax is. In the meantime, the parts I actually use let me get my work done better than any alternatives.
- ygra 12y agoThe problem is that in any existing codebase that is large enough you'll have such a plethora of different things that are used that it doesn't really matter that I don't use things I don't understand or know yet. I still encounter them when reading code and have to understand them then. At least for me who stumbled into a semi-ancient C++ codebase two years ago (and having known almost nothing about the language before) that was a major impediment in picking up how the language should or might be used properly.
- mgkimsal 12y agoGood point, and was most recently used in the PHP community with the introduction of 'goto' about 5 years ago. "If you don't like it, don't use it" is pretty naive, because more often than not, I'm not using my own code, but someone else's (via inherited code, libraries, etc). Code is written once and maintained for years. I've noticed a trend over the years whereby certain types of developers (ab)use new features in a language when first introduced, then move on to other projects, leaving their "my first time with feature X" code behind for someone else to deal with for years to come. Sometimes it's fine, sometimes it's a nightmare. The GOTO thing in PHP has almost been a non-issue all around, but highlighted the "don't use it if you don't like it" argument's flaws.
- lutorm 12y agoWhy does the title slide show a ship flying a US flag? He obviously has correct pictures, because they are in the later slides...
- vinkelhake 12y agoI suppose the ship on the title slide is "the one that sails" (it's not the Vasa).
- wmkn 12y agoBecause it is a pretty picture and the ship with the US flag represents the sailing part in the title of the presentation.
- jokoon 12y agothere are still things I wish would be possible for c++. I'm not a language expert, but I still wish for those things. * non templated tuples instead of struct: for example, 2 struct types are the same if the data types they hold is the same. Not sure if it's possible for statically typed language. * tighter STL container integration with the core language syntax * some way to do modules * some new thing to make compiling much faster, so to avoid relying on precompiled headers. go and rust are so much faster for this, C++ is not. I still wonder if there could be some gcc or clang extension for this, it would be really appreciated. C++ is awesone to work with, but language implementations suffers from those little details.
- loup-vaillant 12y agoML and Haskell are statically typed, and have tuples as you describe them. For instance, the tuple (42, "foo", fun x -> x+3) has type int * string * (int -> int) in ML. It would probably be a serious extension to C++'s type system, though, and for limited benefit: you're asking for yet another way to do Cartesian product. Structs already do that. What's sorely lacking is sum types: type 'a option = Some of 'a | None type 'a list = Cons of 'a * 'a list | Empty --- Integrating the STL at a syntax level gives a special status to the standard library, preventing users from writing effective replacements or analogies. Also, C++ has precious little orthogonality left, let's not destroy it. --- What kind of modules are you talking about? C++ has compilation units, classes, and namespaces. What capability do you want that they don't already provide? --- Good luck on the fast compilation front. That one will likely require removing things from the language, or making some major compatibility-breaking changes in the syntax (to make it easier and faster to parse), and possibly a rework of the template system. No. Way.
- AnimalMuppet 12y agoIf I understand correctly, Go is the "removing things from the language" approach to fixing the fast compilation issue.
- robmccoll 12y ago
- eatitraw 12y agoScott did an amazing talk in Moscow two weeks ago. The slides look the same. Here is the link to the video: http://tech.yandex.ru/events/cpp-party/june-msk/talks/1954/ http://tech.yandex.ru/events/cpp-party/june-msk/talks/1954/
- deleted 12y ago[deleted]
- 4bpp 12y agoThe way people like to complain about the bloat and arbitrariness of C++, but then still quietly wind up using it, reminds me a lot of the common complaints about the arbitrary pronunciation and other quirks of the English language. There is, of course, the trivial commonality that "everyone understands it and a lot of useful things have already been written in it", but at least part of the reason why languages like Esperanto or even Lojban don't catch on is that while many like to extol the virtues of a (natural or machine) language being simple and unambiguous on paper, in practice, more often than not people arrive at a point where they perceive the very un-Pythonic benefit of being able to express the same thing in more than one way (and, conversely, being able to convey more than what the words/code say at face value). The natural language example of course being metaphor and allusion, I am thinking of practices such as indenting glVertex calls inside a glBegin/glEnd block, or overloading () on an object to convey the idea that "you should think of this as something like a function" when it is really not on a technical level.
- rbehrends 12y ago> The way people like to complain about the bloat and arbitrariness of C++, but then still quietly wind up using it Most such people are probably in the same position that I am in, and this is that they're using C++ primarily because they're involved in projects with a C++ legacy codebase. Language choice really isn't something that's up to individual developers. But for personal projects, I've pretty much abandoned C++, other than when I need something to bootstrap on platforms that I can't make a whole lot of assumptions on, or when I have to operate close to the metal and C for some reason or another doesn't fit the bill. The thing is that I don't really have a lot of beef with the language features of C++ (the way they're used in some libraries is a different issue). The features it has are generally there for a reason, and have good rationales. And C++ does pretty well in its chosen domain (system programming). It's not perfect (what programming language is?), but hardly terminally flawed, either. But C++ simply doesn't meet my needs. It has a very strong bias for optimizing CPU cycles, even at the cost of developer cycles, but I'm far more likely to be short on the latter than the former. Those extra few percent of speed that I might gain (or might not -- some C++ features are not all that efficient, after all) are rarely worth adding even a few hours of development time.
- 12y ago
- detrino 12y agoI really enjoyed this talk. The Q&A session was great as well, Scott is an entertaining story teller.
- alexvr 12y agoI think its "excessive" features make it an appealing language so long as I'm not dealing with not-so-well-written and/or expertly "clever" code. I find straightforward, well-written C++ more comprehensible than Java and even Python (only due to Python's dynamic typing). Of course, the definition behind straightforward, well-written C++ is very subjective.
- santaclaus 12y agoWhy can't we simply have C + RAII + generics? That would be a baller language.
- 10098 12y agothrow in first-order functions and lambdas as well, replace generics with templates the way they are now, and I'm all for that!
- Tomte 12y agoWhen in Stockholm, go visit the Vasa museum. It's absolutely breathtaking. Make sure to get a guided tour. You can read all the stuff on the displays and in books, but you probably won't. So you'd lose all those nice stories about how the German ambassador protested the ship, because the figurines on the front symbolized the Roman emperors, with the Swedish king at the very front. Preposterous! The emperor of the Holy Roman Empire of the German Nation is the rightful successor to the Roman emperors, after all! Pay attention to the fact that the Swedes weren't as stupid as people tend to assume. "Oh, they couldn't even build a ship that's floating!". Yeah well, it was a design no-one had attempted before (bigger, three masts, two rows of cannons), the math to calculate the behaviour wasn't available, yet. And best of all -- contemporary analysis shows that they almost made it. Had the ship been just a little bit wider (I don't know, something like 20 centimeters or so?), it would have been fine. Be amazed how the Swedes never just found a scapegoat to punish for the loss of their flagship. Or just admire the architecture of the museum. Whenever I'm in Stockholm I go there. It's inevitably a high point of my visits.
- bjourne 12y agoSeveral people working on the design of the ship knew it never would sail. But since voicing their criticism about the king's unrealistic spec carried the risk of getting beheaded they kept their mouths mostly shut. The master shipbuilder who was in charge of the project fled back to Holland when Vasa sank. It was a classic case of hoping someone else would get the blame when the shit hits the fan.
- tragic 12y agoI'd completely forgotten about that. Yes, it's a great bit of tourism - very interesting building. On the over-arming of ships going spectacularly wrong, see also the Mary Rose[1]. [1] http://en.wikipedia.org/wiki/Mary_Rose http://en.wikipedia.org/wiki/Mary_Rose
- mrev19 12y agoThe second row of cannons was added at the insistence of the king, the shipbuilder knew it would doom the ship. Also, I've yet to meet anyone who thought the Vasa sank because "Swedes were stupid."
- vasilipupkin 12y agoI've been using C++ for many years, and, sure, it has a ton of various features, not all of which I use all of the time. But, being comfortable with it, I don't find it any harder to program in than Java or Python. I am not sure if it's fair to say that the learning curve is higher to get to that point. But then again, if you do silly things in Java, won't your code be slow as well?
- vilya 12y agoThe line that stood out to me was the quote from Stepanov, about C++ being the only language in which it was possible to implement the STL. To most people, that would have been a hint that perhaps the design of the STL was flawed... I think the STL may have been the worst thing to have happened to C++. It could have been so much nicer if something like Qt (the core part) was adopted instead.
- stinos 12y agoI think the STL may have been the worst thing to have happened to C++ I think opinions on that greatly vary. I for one find a majority of what is in STL very well-designed and very usable.
- vilya 12y agoSure, I was just giving my opinion. Take it for what it's worth... :-) But if you'll indulge me for a moment, consider how you'd convert a string to uppercase using the STL vs using Qt. The STL code (taken from http://en.cppreference.com/w/cpp/algorithm/transform http://en.cppreference.com/w/cpp/algorithm/transform) looks like this: std::string tmp = s; std::transform(tmp.begin(), tmp.end(), tmp.begin(), std::ptr_fun<int, int>(std::toupper)); return tmp; Note the use of a temporary variable, because std::transform does a destructive update. The equivalent Qt code looks like: return s.toUpper(); I'll let you draw your own conclusions. By the way if there's a simpler way to do that using the STL, I'd love to hear about it.
- humanrebar 12y agoIt should be (eliding namespaces): transform(begin(tmp), end(tmp), begin(tmp), [] (char c) { return toupper(c); }); ...the only noisy parts are the calls to begin() and end(). On the other hand, it will work for any collection type with good iterators (vectors, lists, strings, deques, ropes, etc.). It is also trivial to write a mylib::transform_in_place() that cuts down on the noise with a one-line function.
- 12y ago