Wednesday, August 20, 2014

Near-Final Draft of Effective Modern C++ Now Available (plus TOC and sample Item)

Effective Modern C++ is moving closer and closer to reality. This post contains:
  • Information about availability of an almost-final draft of the book.
  • The current (and probably final) table of contents.
  • A link to the I-hope-I-got-it-right-this-time version of my Item on noexcept.

Draft Book Availability

A revised and nearly-final manuscript is now available through O'Reilly's Early Release Program and Safari Books Online's Rough Cuts program. The prose still needs to be sanded down a bit, but practically speaking, this is the final stream of words that will make up the book. Remaining tasks include double-checking the code samples, index generation and final formatting (i.e., typesetting), but this should be quite close to what gets published.

I've left the line numbers in for the online drafts, because that makes it easier for people to report errors to me. The really truly honest-this-is-it version of the manuscript is due to O'Reilly in early September, so if you see anything that needs improvement, please let me know by the end of this month!

Probably-Final Table of Contents

Here's the current table of contents. I'm not wild about the title of the final chapter ("Tweaks"), so if you have suggestions for a better title, let me know.
CHAPTER 1  Deducing Types
  Item 1:  Understand template type deduction. 
  Item 2:  Understand auto type deduction. 
  Item 3:  Understand decltype. 
  Item 4:  Know how to view deduced types. 

CHAPTER 2  auto
  Item 5:  Prefer auto to explicit type declarations. 
  Item 6:  Use the explicitly typed initializer idiom when auto deduces 
           undesired types. 

CHAPTER 3  Moving to Modern C++
  Item 7:  Distinguish between () and {} when creating objects. 
  Item 8:  Prefer nullptr to 0 and NULL. 
  Item 9:  Prefer alias declarations to typedefs. 
  Item 10: Prefer scoped enums to unscoped enums. 
  Item 11: Prefer deleted functions to private undefined ones. 
  Item 12: Declare overriding functions override. 
  Item 13: Prefer const_iterators to iterators. 
  Item 14: Declare functions noexcept if they won't emit exceptions. 
  Item 15: Use constexpr whenever possible. 
  Item 16: Make const member functions thread-safe. 
  Item 17: Understand special member function generation. 

CHAPTER 4  Smart Pointers
  Item 18: Use std::unique_ptr for exclusive-ownership resource management. 
  Item 19: Use std::shared_ptr for shared-ownership resource management. 
  Item 20: Use std::weak_ptr for std::shared_ptr-like pointers that can dangle.
  Item 21: Prefer std::make_unique and std::make_shared to direct use of new.
  Item 22: When using the Pimpl Idiom, define special member functions in the
           implementation file.

CHAPTER 5  Rvalue References, Move Semantics, and Perfect Forwarding
  Item 23: Understand std::move and std::forward. 
  Item 24: Distinguish universal references from rvalue references. 
  Item 25: Use std::move on rvalue references, std::forward on universal
           references.
  Item 26: Avoid overloading on universal references. 
  Item 27: Familiarize yourself with alternatives to overloading on universal 
           references.
  Item 28: Understand reference collapsing. 
  Item 29: Assume that move operations are not present, not cheap, and not used. 
  Item 30: Familiarize yourself with perfect forwarding failure cases. 

CHAPTER 6  Lambda Expressions
  Item 31: Avoid default capture modes. 
  Item 32: Use init capture to move objects into closures. 
  Item 33: Use decltype on auto&& parameters to std::forward them. 
  Item 34: Prefer lambdas to std::bind. 

CHAPTER 7  The Concurrency API
  Item 35: Prefer task-based programming to thread-based. 
  Item 36: Specify std::launch::async if asynchronicity is essential. 
  Item 37: Make std::threads unjoinable on all paths. 
  Item 38: Be aware of varying thread handle destructor behavior. 
  Item 39: Consider void futures for one-shot event communication. 
  Item 40: Use std::atomic for concurrency, volatile for special memory. 

CHAPTER 8  Tweaks
  Item 41: Consider pass by value for copyable parameters that are cheap to 
           move and always copied.
  Item 42: Consider emplacement instead of insertion. 
Technical writing archeologists may wish to compare this TOC with the versions I showed on 18 March 2014, 5 April 2013, and 29 January 2013. I told you things would change!

Close-to-Final Item on noexcept

I posted drafts of my Item on noexcept on 31 March 2014 and 4 February 2014, so I felt obliged to show you the final-unless-I've-really-made-a-serious-mistake version. Here it is:
Let me know what you think. You've never been shy before, and I have no reason to think things will be different this time around :-)

Scott


43 comments:

  1. Couldn't Items 41 and Item 42 fit at the end of Chapter 5? I think that would make sense as practical tips based on the previous Chapter 5 items.

    ReplyDelete
  2. @Neil: I could put them at the end of Chapter 5, but they don't really fit there. They're not really about how rvalue references or perfect forwarding or move semantics work, they're about balancing a number of different factors, some of which relate to rvalue references and some of which do not.

    I originally had them as part of chapter 3, but the more I learned about the issues involved, the clearer it became that they didn't really fit there, either.

    ReplyDelete
  3. Loving the book! Chapter titles:

    "Great Scott! But I think I should..."

    "Potential banana skins"

    "So you think this is easy, huh?"

    "Exceptional items"

    "(In)effective modern C++"

    "Bonus items!"

    "Optimizations to the previous items"

    ReplyDelete
  4. Chapter 8: "Optimizations"

    Too pedestrian? :)

    ReplyDelete
  5. The noexcept item looks great to me, and I think you came up with a good title for it.

    ReplyDelete
  6. @David Grigsby: I think two Items is too short to justify a title of "Optimizations". Also, Item 41 ("Consider pass by value for copyable parameters that are cheap to move and always copied") isn't about an optimization in the normal sense of the word, because it proposes something that is likely to run more slowly. The advantage of that tweak is that it can simplify your source code at a relatively modest cost in performance.

    ReplyDelete
  7. @Seth: I'm glad you think the new title strikes a more appropriate tone for the Item.

    ReplyDelete
  8. Option 1: Move item 41 to the end of chapter 5 and item 42 to somewhere in chapter 3.

    Option 2: Tell your publisher that you're delaying the final publication a few months to come up with 8 more optimizations/advanced topics. After all, "50 Specific Ways" sounds a lot better than 42...

    ReplyDelete
  9. Nope, 42 items is fine. Also, call the book "The Hitchhiker's Guide to C++" and put a friendly "Don't Panic" sticker on it. Sell a deluxe version with a towel. Just an idea ;)

    ReplyDelete
  10. Hi Scott,

    I've read through the Free Sampler of the book and I think you've done a great job of explaining the reasoning behind the type deduction rules :)

    Also, I noticed what I believe to be a mistake on page 28, line 11, it says: "C++11 permits return types for single-statement lambdas to be deduced" This is not true. Perhaps you were thinking of constexpr functions?

    ReplyDelete

  11. @Michael Park: Return type deduction in single statement lambdas is supported!

    e.g. [](int x) { return x * 2.; }

    yields the return type «double» for the lambda…

    ReplyDelete
  12. Ah I didn't realize I wasn't clear about this.

    I'm saying that return type deduction in multiple-statements lambdas work in C++11 as well, not that single-statement lambdas don't work.

    For example, the return type of

    []() {
    double result = 0;
    for (int i = 0; i < 10; ++i) {
    result += i;
    }
    return result;
    }

    also gets deduced to double.

    ReplyDelete
  13. Michael, deducing the return type of a multiple-statement lambda requires C++14.

    ReplyDelete
  14. @Marcel Marré: I like your thinking about marketing :-)

    ReplyDelete
  15. Ah, that's my mistake. I thought #975 had made it into C++11. Also didn't help that both gcc and clang accepts the above code with -std=c++11, but that's a rookie mistake on my part.

    ReplyDelete
  16. Do you want reports of typos posted here? e.g. page 26, line 26: "lamba parameter" should be "lambda parameter".

    ReplyDelete
  17. @mattnewport: I'm happy to get bug reports in whatever form is easiest for you: blog comments, email, private courier or drone, etc.

    Regarding this particular mistake, (1) thank you for reporting it, and (2) MS Word has decided that my document has too many misspelled words, so it no longer performs spell checking as I type. Sigh.

    ReplyDelete
  18. Another suggestion for the last chapter tittle:

    "Other Considerations"

    ReplyDelete
  19. @Joe Gottman: Thanks for the suggestion, but given the Items in that chapter, I think "Tweaks" captures the mood a bit better. But we'll see what others say.

    ReplyDelete
  20. I've not seen it asked so I wanted to get some personal clarity. Is Effective Modern C++ to be considered a companion book to be added to the rest of the Effective collection of books or should it be considered a stand alone book?

    ReplyDelete
  21. @Clayton Weaver: I'd say that both are true. It doesn't cover any of the topics addressed in my other books, but it doesn't assume you've read the other books, either.

    You can read a little more about how it relates to my other books here. And of course you can read the sample chapter and the sample Item accompanying this post to get a sense for the content of the book.

    ReplyDelete
  22. @David Grigsby: Well, "Tweaks" is slightly more specific than "Miscellanea" :-)

    ReplyDelete
  23. But does it explain his hair?

    ReplyDelete
  24. a. Consider swapping the order of Items 39 and 40.
    b. Then, consider moving (the newly swapped) Item 40 from Chapter 7 to Chapter 8.
    c. Finally, consider renaming Chapter 8 "Considerations".

    Moon

    ReplyDelete
  25. @D Moon: Ah, move all the "Consider" Items together. Interesting. Thanks for the suggestion.

    ReplyDelete
  26. On first reading of the sentences where you talk about various metaphors (page 6, line 7+), I was a bit confused by the sentences starting with Is. My mind thought it should be "It's" rather than "Is". When I re-read I see that you're saying to use them in place of your previous example. The full stops were stopping me linking them back to the previous metaphor without some thought. I've no suggestion on how to overcome this.

    ReplyDelete
  27. @Phil Wright: I'm sorry you stumbled over those sentences. I thought that was a pretty common kind of construct, but perhaps I was mistaken. Maybe it's only pretty common for me :-)

    ReplyDelete
  28. Possible Word Crime: Page 43 line 5, the "however" seems redundant. With a a spot check of grammar sites it appears you are on very shaky ground. :)

    ReplyDelete
  29. Page 47 line 4: suggest "matter is that". [I'll send any more like this in an email to not bloat your blog comments.]

    ReplyDelete
  30. @David Grigsby: Regarding page 43, I think it reads better with "however," so I'll risk the wrath of the language police. Regarding page 47, that's an error that I've already fixed.

    Keep 'em coming in whatever form you prefer.

    ReplyDelete
  31. Is it possible to pre-order the final book, and get a draft copy to read on my Kindle now?

    I followed the O'Reilly and Safari Books links, but I didn't see this as an option.

    BTW, just want to say that "Effective C++" was the pivotal book for me back in the early '90s. I was making the transition from C to C++ and I loved the style of making an assertion (e.g. "prefer this to that"), and then justifying the assertion by going through the thought process, examining the pros and cons of each alternative.

    I read through it once, then would occasionally browse through the TOC until I found some assertion that I couldn't remember the justification for, and would re-read that chapter. This book taught me what to do, why to do it, and the thinking involved in future design decisions. Through the years, I've recommended your book to lots of younger developers.

    ReplyDelete
  32. @Scott Smith: Thanks for your kind words about Effective C++. I hope that you find Effective Modern C++ as useful.

    If you want to buy the digital book, then you can do what you want. If you want to order the print+digital combination to get access to the digital book now, that does not seem to be possible. From my editor (as quoted in the comment thread for this post):

    We do not sell the early release with a pre-order of the print book due to systems issues (and possibly laws around taking credit card numbers without charging them or something). It is something that we have on our list to work on in future.

    My editor and I agree that this makes no sense, but we have no control over it, sorry.

    ReplyDelete
  33. FYI, there is some debate about a point in Item 6 over at Stack Overflow:
    http://stackoverflow.com/questions/25607216/why-should-i-prefer-the-explicitly-typed-initializer-idiom-over-explicitly-giv - could you share your thoughts about it?

    ReplyDelete
  34. @Mathieu Seigneurin: Item 5 argues that you should get into the habit of using auto. Item 6 points out that in some cases, auto will deduce the wrong type, so the question is what to do when that happens. Mario (the poster of the question at StackOverflow) lays out the alternatives: (1) don't use auto, (2) use auto with static_cast, (3) use auto with a C-style cast.

    I think the arguments against C-style casts are both well known and compelling, so the real choice is between using auto and not using auto. The advantages of using auto are that (1) it's a good habit to get into (i.e., using it is consistent with the advice in Item 5) and (2) you can't forget to initialize the variable you're declaring.

    As Mario points out, using auto is more typing than the alternatives, so you have to decide what's most important to you. If reinforcing the habit of using auto is most important, you're likely to be willing to blow some extra keystrokes in those few situations where auto will deduce the wrong type. If reducing verbosity is more important, you'll probably go with an explicit type declaration (i.e., you won't use auto).

    Feel free to post these comments to SO if you think they would be useful.

    ReplyDelete
  35. Thank you for the update.

    I noticed that the paragraph named “beyond typeid” has disappeared in this version. It was about __PRETTY_FUNCTION__, __FUNCSIG__ and other implementation-specific ways to know the types of the variables involved.

    I thought it was very interesting. I suppose that you removed it because it was not about C++11 or C++14 new language features, so it is out of scope for a book called “… Modern C++”, and also because compiler extra features are by essence not portable and could even be removed in the future, so it could be a bad habit to rely on those.

    Nevertheless I would appreciate if you restored that subsection, at least in a footnote.

    ReplyDelete
  36. @Benoit M: I decided that Boost.TypeIndex was a preferable thing to mention, because it has the same interface across multiple platforms. The information I used to have on __PRETTY_FUNCTION__, etc., won't go back in the book, but I might publish it online as a blog entry.

    ReplyDelete
  37. For Chapter 8: perhaps "Micro-Optimizations"?

    ReplyDelete
  38. @Rotsiser Mho: I decided to stick with "Tweaks". The final manuscript went in at the end of August.

    ReplyDelete
  39. @Scott - Item 16 concerns me as it seems to assume multiple threads would only be calling const members, and indeed were that the case, say an immutable object with `mutable` implementation, then the point is well made. But it seems to gloss over the fact that only making const members thread safe is not sufficient if there are non-const members.

    ReplyDelete
  40. @James Crotinger: Non-const member functions are conceptually write operations, and multiple threads should never invoke multiple write operations on an object without proper synchronization. Doing so always leads to undefined behavior. const member functions get special treatment, because they represent reads, and callers should be able to assume that multiple threads may invoke read operations without any need for synchronization. The problem arises when const member functions perform writes, as can be the case with caching implementations. Item 16 addresses such cases.

    ReplyDelete
  41. Thanks Scott. I understand. Just thought this might be mentioned in the item.

    ReplyDelete
  42. @James Crotinger: I would hope that nobody would assume that if all const member functions are thread safe, that would somehow resolve all thread safety issues.

    ReplyDelete