hn-classics/_stories/2006/11978875.md

26 KiB
Raw Permalink Blame History

created_at title url author points story_text comment_text num_comments story_id story_title story_url parent_id created_at_i _tags objectID year
2016-06-26T00:52:28.000Z My Most Important C++ Aha Moments (2006) http://www.artima.com/cppsource/top_cpp_aha_moments.html adamnemecek 100 81 1466902348
story
author_adamnemecek
story_11978875
11978875 2006

Source

My Most Important C++ Aha! Moments...Ever

| ----- | |

|

| ----- | | The Artima Developer Community |

| -----|
|

Articles| News| Weblogs| Buzz| Books| Forums

|

| ----- | |

The C++ Source | C++ Community News | Discuss | Print | [Email][13] | First Page | [Previous][14] | Next

|

| ----- | |

Sponsored Link • ![][15]

|

The C++ Source
A Pause to Reflect: Five Lists of Five, Part V
My Most Important C++ Aha! Moments...Ever
Opinion
by Scott Meyers
September 6, 2006

| ----- | |

Advertisement

![][16]

|

Summary

In this article, Scott Meyers shares his picks for the five most meaningful Aha! moments in his involvement with C++, along with why he chose them.

In the first four articles in this series, I named my picks for the most important contributions to C++ in the categories of books, non-book publications, software, and people:

  • “[The Most Important C++ Books...Ever”][17]
  • “[The Most Important C++ Non-Book Publications...Ever”][18]
  • “[The Most Important C++ Software...Ever”][19]
  • “[The Most Important C++ People...Ever”][20]

In this fifth and final installment, I name my five biggest Aha! moments in C++.

You do this job long enough, youre going to have a few moments when the big pieces of the puzzle come together, and things suddenly make sense. (If not, youve made a poor choice of profession.) When those rare moments occur, I cant help but inhale quickly and freeze, staring off into the distance as if the world, which had heretofore been black and white, suddenly snapped into color. And then I smile. Such moments are intense. Confusion vanishes. Understanding takes its place.

One revelation of this ilk took place in 1978, when, after a period of struggle, I suddenly realized how pointers work: a computing coming of age if ever there was one. But I was programming in Pascal at that time, so it doesnt make the list of my five most important C++-related “Aha!” moments. Here are the ones that do:

  • **Realizing that C++s “special” member functions may be declared private[**1][21], 1988. Like many of my friends, I was teaching myself C++ at the time. One day a fellow graduate student, John Shewchuk, came into the office with a problem hed been wrestling with. “How do you keep an object from being copied?,” he asked. There were several of us present, and none of us could figure out how. We knew that if you didnt declare the copy constructor and copy assignment operator, compilers would generate them automatically, and the resulting objects would be copyable. We also knew that the only way to prevent compilers from generating those functions was to declare them manually, but then the functions would exist, and, we reasoned, the objects would again be copyable. Like the Grinch,[2][22] we puzzled and puzzled, but none of us was able to find a way to resolve this conundrum.

Later that day (or perhaps the next day, I dont remember), John came back and announced that hed figured it out: the copying functions could simply be declared private. Of course! But at the time it was a revelation, a critical step on my understanding of how the pieces of C++ fit together. When I wrote the first edition of Effective C++ some three years later, this simple insight earned its own Item. (At under a page long, its possibly the shortest Item in the book.) That I continue to find the insight important is reflected in the fact that Ive included it in both subsequent editions of Effective C++. I didnt think there was anything obvious about declaring the implicitly generated functions private in 1988, and I feel the same way in 2006.

  • Understanding the use of non-type template parameters in Bartons and Nackmans approach to dimensional analysis, 1995. In May 1988, I read the IEEE Software article, “Dimensional Analysis with C++,” by Robert F. Cmelik and Narain H. Gehani. They described an approach to detecting units errors in computations involving physical units, e.g., distances, velocities, time, etc. For example, dividing a distance by time and comparing that to a velocity is fine, but comparing it to an acceleration (which represents distance divided by time squared) is not. Cmeliks and Gehanis solution involved storing information about the units inside the objects and performing runtime check to detect errors. That increased object sizes and also increased runtimes. It seemed to me that there should be a better way to address the problem, but after another round or two of fruitless puzzling, I stopped thinking about the matter.

John J. Barton and Lee R. Nackman described a wonderful solution to the units problem in their 1994 book, Scientific and Engineering C++ (Addison-Wesley), but even though I received a copy of the book, I didnt notice their work when it came out. To be honest, I found the book rather boring, and I read little of it. However, I read Bartons and Nackmans column in the January 1995 C++ Report in its entirety, and that column presented a stripped-down (and vastly more readable) version of their approach. Three things about it struck me. First, it covered all possible combinations of units, not just the combinations with names. That is, we have a name for distance divided by time (velocity) and for force divided by distance squared (pressure), but we dont have a name for distance times time squared divided by angular velocity cubed. At least not one that I know of. The B&N; approach ensures dimensional unit correctness, even if calculations yield heretofore unneeded combinations of units.

The second thing that got my attention about the B&N; solution was its runtime cost: there isnt any. Objects get no bigger, and programs get no slower. The B&N; approach thus covers everything and costs nothing.[3][23] Thats the kind of combination that makes me pay attention.

But what really transported me to the giddy land of Aha! was their use of non-type template parameters to represent the exponents of the various fundamental units and their use of arithmetic operations on these parameters to calculate the resulting unit types.[4][24] So not only did they solve a practical problem that had piqued my interest years before, they did it by applying a feature of C++ (non-type template parameters) that until then had struck me as more a curiosity than anything else.

I get excited about Bartons and Nackmans work even now, and I wish I could have included their C++ Report column on my list of the most important [non-book C++-related publications][18], but from what I can tell, few people found their work as revolutionary as I did, and it had little impact. To this day I think thats a shame, because I cherish the flash of understanding their column engendered in me.

  • Understanding what problem Visitor addresses, 1996 or 1997. A bedrock software engineering principle is that good names are important, and this is a case where a poor name tripped me up. I dont recall having a particular problem following the mechanics of the Visitor design pattern, but it never made any sense to me. I just couldnt grasp how the pieces fit together. Then, one day, I made a fundamental realization: the Visitor Pattern has nothing to do with visitation. Rather, its a way to design hierarchies so that new virtual-acting functions can be added without changing the hierarchies. Once I grasped that, the pattern was easy to understand. But the name was a real stumbling block for me, even though [Design Patterns][25] documents this as part of the patterns intent:

Visitor lets you define a new operation without changing the classes of the elements on which it operates.

Thats about as clear and straightforward as you can get, but because I was so fixated on the patterns name, I couldnt get past the idea that Visitor had something to do with visitation or iteration or something like that.

There are two possible conclusions here. One is that Im so dense, Im surrounded by a small event horizon. The other is that names should be chosen carefully, because if a name suggests one thing and the documentation says another, at least some people—if only exceedingly dense ones—will be misled. I prefer the latter interpretation.

  • Understanding why remove doesnt really remove anything, 1998? My relationship with the STL remove algorithm did not begin on an auspicious note. Just as I expected the Visitor design pattern to visit things, I expected the remove algorithm to remove things. It was thus with considerable shock and a feeling of betrayal that I discovered that applying remove[5][26] to a container never changes the number of elements in the container, not even if you ask it to remove everything. Fraud! Deceit! False advertising!

Then one day I read a column—possibly Andrew Koenigs “C++ Containers are Not Their Elements” (C++ Report, November-December 1998)—that made clear to me a fundamental STL truth: algorithms can never change the number of elements in a container, because algorithms dont know what container they are operating on. The “container” might in fact be an array, and certainly there is no way to change the size of an array. [6][27] This is a natural fallout of the fact that algorithms and containers are independent and know nothing about one another. remove, I realized, didnt change the number of elements in a container, because it couldnt. It was at that moment that I really began to understand the architecture of the STL, to appreciate that iterators, though typically served up by container member functions, were quite separate entities, ones on a par with containers and algorithms. Id read that many times before. Id probably even parroted it back in presentations Id given. But this was the first time I really understood it.

From then on, remove and I got along a lot better, and when I later realized that not only did remove do as well as it could given what it had to work with, it also did what it did better than most programmers who write their own loops (remove runs in linear time, but naïve loops run in quadratic time), I developed a grudging respect for remove. Im still not wild about the name, but its not clear what name it could have that would both accurately summarize what it does and be easy to remember.

  • Understanding how deleters work in Boosts shared_ptr, 2004. Boosts reference-counting smart pointer shared_ptr has the interesting characteristic that you can pass it a function or function object during construction, and it will invoke this deleter on the pointed-to object when the reference count goes to zero.[7][28] At first blush, this seems unremarkable, but look at the code:

      template<typename T>
    

    class shared_ptr { public: template<typename U, typename D> explicit shared_ptr(U* ptr, D deleter); ... };

Notice that a shared_ptr<T> must somehow arrange for a deleter of type D to be invoked during destruction, yet the shared_ptr<T> has no idea what D is. The object cant contain a data member of type D, nor can it point to an object of type D, because D isnt known when the objects data members are declared. So how can the shared_ptr object keep track of the deleter that will be passed in during construction and that must be used later when the T object is to be destroyed? More generally, how can a constructor communicate information of unknown type to the object it will be constructing, given that the object cannot contain anything referring to the type of the information?

The answer is simple: have the object contain a pointer to a base class of known type (Boost calls it sp_counted_base), have the constructor instantiate a template that derives from this base class using D as the instantiation argument (Boost uses the templates sp_counted_impl_p and sp_counted_impl_pd), and use a virtual function declared in the base class and defined in the derived class to invoke the deleter. (Boost uses dispose). Slightly simplified, it looks like this:

![][29]

Its obvious—once youve seen it. [8][30],[9][31] But once youve seen it, you realize it can be used in all kinds of places, that it opens up new vistas for template design where templatized classes with relatively few template parameters (shared_ptr has only one) can reference unlimited amounts of information of types not known until later. Once I realized what was going on, I couldnt help but smile and shake my head with admiration.[10][32]

Okay, thats it, the last of my “five lists of five.” For the record, heres a summary of this series of articles: what I believe to be the five most important books, non- book publications, pieces of software, and people in C++ ever, as well as my five most memorable “Aha!” moments. Ill spare you another such exercise in narcissism for at least another 18 years.

  • “[The Most Important C++ Books...Ever”][17]
    • The C++ Programming Language by Bjarne Stroustrup
    • Effective C++ by Scott Meyers
    • Design Patterns by Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides
    • International Standard for C++
    • Modern C++ Design by Andrei Alexandrescu
  • “[The Most Important C++ Non-Book Publications...Ever”][18]
    • Programming in C++, Rules and Recommendations_ by Mats Henricson and Erik Nyquist
    • “Exception Handling: A False Sense of Security” by Tom Cargill
    • “Curiously Recurring Template Patterns,” by Jim Coplien
    • “Using C++ Template Metaprograms” by Todd Veldhuizen
    • “Exception-Safety in Generic Components” by David Abrahams
  • “[The Most Important C++ Software...Ever”][19]
    • Cfront by AT&T; Bell Telephone Laboratories
    • GCC by the GNU Project
    • Visual C++ by Microsoft
    • The Standard Template Library, originally by HP
    • The Libraries at Boost
  • “[The Most Important C++ People...Ever”][20]
    • Bjarne Stroustrup
    • Andrew Koenig
    • Scott Meyers
    • Herb Sutter
    • Andrei Alexandrescu
  • “[My Most Important C++ Aha! Moments...Ever”][33]
    • Realizing that C++s “special” member functions may be declared private
    • Understanding the use of non-type template parameters in Bartons and Nackmans approach to dimensional analysis
    • Understanding what problem Visitor addresses
    • Understanding why remove doesnt really remove anything
    • Understanding how deleters work in Boosts shared_ptr ![][34]

Share Your Opinion

Discuss this article in the Articles Forum topic, [My Most Important C++ Aha! Moments...Ever][35].

End Notes

  1. It likely goes without saying that C++s “special” member functions—and the Standard calls them that—are the default constructor, copy constructor, copy assignment operator, and destructor. What makes them special is that compilers are generally willing to implicitly generate them if they are used but not explicitly declared.

  2. An allusion to the couplet, “And the Grinch, with his grinch-feet ice-cold in the snow, Stood puzzling and puzzling: How could it be so?’” from How the Grinch Stole Christmas by Dr. Seuss, Random House, 1957, text available online (dont tell Random House) at http://www.kraftmstr.com/christmas/books/grinch.html.

  3. Costs nothing at runtime, that is. Their at-that-time advanced use of templates certainly increased compilation times.

  4. When you multiply two values, you add their exponents, remember?

  5. The algorithm, not the list member function.

  6. realloc doesnt count; not all arrays are dynamically allocated.

  7. TR1s shared_ptr—which, unsurprisingly, is based on Boosts shared_ptr—offers the same behavior. Here Im discussing Boosts shared_ptr, because that has an implementation, and this is an implementation issue. TR1 is just a specification, so, if you want to be pedantic, asking how something in TR1 is implemented is meaningless.

  8. More precisely, once youve had it explained to you. In my case, the explanation came, as it has so often during my association with C++, courtesy of a discussion in a Usenet newsgroup (see http://tinyurl.com/r66ql for details).

  9. Its also, I believe, an example application of the [External Polymorphism][36] (PDF) design pattern, a pattern Ive liked ever since I read about it (“External Polymorphism,” Chris Cleeland and Douglas C. Schmidt, C++ Report, September 1998), but one that, until now, Id never seen in action.

  10. My personal “Aha!ness” of this story aside, there are two other aspects to this tale worth mentioning (but only in a note, apparently). First, this is an example of the kind of implementation innovation fostered at Boost, and such innovation is one of the reasons why I chose it for my list of the most important C++-related software. Second, I think its regrettable that this kind of innovation doesnt often get written up and disseminated for the wider C++ development community. Boost does an enviable job of fostering the creation of useful software, including user-level documentation that is at least serviceable. I wish it did a better job of getting the word out on the design and implementation techniques employed by the library authors, because theres some really interesting—and largely unknown—stuff going on under the hood in Boost libraries.

Resources

Part I in this series, “The Most Important C++ Books...Ever”:
[http://www.artima.com/cppsource/top_cpp_books.html][17]

Part II, “The Most Important C++ Non-Book Publications...Ever”:
[http://www.artima.com/cppsource/top_cpp_publications.html][18]

Part III, “The Most Important C++ Software...Ever”:
[http://www.artima.com/cppsource/top_cpp_software.html][19]

Part IV, “The Most Important C++ People...Ever”:
[http://www.artima.com/cppsource/top_cpp_people.html][20]

Scott Meyers is the author of Effective C++, the third edition of which was published in 2005. It is available on Amazon.com at:
[http://www.amazon.com/exec/obidos/ASIN/0321334876/][37]

Scott Meyers is also the author of More Effective C++, which is available on Amazon.com at:
[http://www.amazon.com/exec/obidos/ASIN/020163371X/][38]

Scott Meyers is also the author of Effective STL, which is available on Amazon.com at:
[http://www.amazon.com/exec/obidos/ASIN/0201749629/][39]

Scott Meyers home page:
http://www.aristeia.com/

About the Author

![Scott Meyers][40] Scott Meyers is one of the worlds foremost authorities on C++; he provides training and consulting services to clients worldwide. He wrote the best-selling Effective C++ series ([Effective C++][41], [More Effective C++][42], and [Effective STL][43]), designed the innovative [Effective C++ CD][44], is Consulting Editor for Addison Wesleys [Effective Software Development Series][45], and serves on the Advisory Board for The C++ Source ([http://www.artima.com/cppsource/][46]). He has a Ph.D in Computer Science from Brown University. His web site is [aristeia.com][47].

The C++ Source | C++ Community News | Discuss | Print | [Email][13] | First Page | [Previous][14] | Next


| ----- | |

Sponsored Links

|


| ----- | | [ ![Google][48]][49] | |
|   | Web Artima.com    |

[Copyright][50] © 1996-2018 Artima, Inc. All Rights Reserved. - [Privacy Policy][51] - [Terms of Use][52]

"); } function replaceDiv(divID) { document.getElementById(divID).innerHTML = phpadsbanner; } -->

[13]: mailto:?subject=My Most Important C++ Aha! Moments...Ever&body= %0AMy Most Important C++ Aha! Moments...Ever %0AOpinion %0Aby Scott Meyers %0A%0Ahttps://www.artima.com/cppsource/top_cpp_aha_moments.html [14]: https://www.artima.com/cppsource/top_cpp_people.html [15]: https://www.artima.com/zcr/adview.php?what=zone:9&n=a0587811 [16]: https://www.artima.com/zcr/adview.php?what=zone:2&n=a799ecf6 [17]: https://www.artima.com/top_cpp_books.html [18]: https://www.artima.com/top_cpp_publications.html [19]: https://www.artima.com/top_cpp_software.html [20]: https://www.artima.com/top_cpp_people.html [21]: https://www.artima.com#r1 "It likely goes without saying that C++s “special” member functions—and the Standard calls them that—are the default constructor, copy constructor, copy assignment operator, and destructor. What makes them special is that compilers are generally willing to implicitly generate them if they are used but not explicitly declared." [22]: https://www.artima.com#r2 "2. An allusion to the couplet, “And the Grinch, with his grinch-feet ice-cold in the snow, Stood puzzling and puzzling: How could it be so?’” from How the Grinch Stole Christmas by Dr. Seuss, Random House, 1957, text available online (dont tell Random House) at http://www.kraftmstr.com/christmas/books/grinch.html." [23]: https://www.artima.com#r3 "3. Costs nothing at runtime, that is. Their at-that-time advanced use of templates certainly increased compilation times." [24]: https://www.artima.com#r4 "4. When you multiply two values, you add their exponents, remember?" [25]: https://www.artima.com/top_cpp_books.html#dp [26]: https://www.artima.com#r5 "5. The algorithm, not the list member function." [27]: https://www.artima.com#r6 "6. realloc doesnt count; not all arrays are dynamically allocated." [28]: https://www.artima.com#r7 "7. TR1s shared_ptr—which, unsurprisingly, is based on Boosts shared_ptr—offers the same behavior. Here Im discussing Boosts shared_ptr, because that has an implementation, and this is an implementation issue. TR1 is just a specification, so, if you want to be pedantic, asking how something in TR1 is implemented is meaningless." [29]: https://www.artima.com/images/sharedPtr.gif [30]: https://www.artima.com#r8 "8. More precisely, once youve had it explained to you. In my case, the explanation came, as it has so often during my association with C++, courtesy of a discussion in a Usenet newsgroup (see http://tinyurl.com/r66ql for details)." [31]: https://www.artima.com#r9 "9. Its also, I believe, an example application of the External Polymorphism design pattern, a pattern Ive liked ever since I read about it (“External Polymorphism,” Chris Cleeland and Douglas C. Schmidt, C++ Report, September 1998), but one that, until now, Id never seen in action." [32]: https://www.artima.com#r10 "10. My personal “Aha!ness” of this story aside, there are two other aspects to this tale worth mentioning (but only in a note, apparently). First, this is an example of the kind of implementation innovation fostered at Boost, and such innovation is one of the reasons why I chose it for my list of the most important C++-related software. Second, I think its regrettable that this kind of innovation doesnt often get written up and disseminated for the wider C++ development community. Boost does an enviable job of fostering the creation of useful software, including user-level documentation that is at least serviceable. I wish it did a better job of getting the word out on the design and implementation techniques employed by the library authors, because theres some really interesting—and largely unknown—stuff going on under the hood in Boost libraries." [33]: https://www.artima.com/top_cpp_aha_moments.html [34]: https://www.artima.com/images/ig.gif [35]: http://www.artima.com/forums/flat.jsp?forum=226&thread=175294 [36]: [37]: http://www.amazon.com/exec/obidos/ASIN/0321334876/billvennersA/ [38]: http://www.amazon.com/exec/obidos/ASIN/020163371X/billvennersA/ [39]: http://www.amazon.com/exec/obidos/ASIN/0201749629/billvennersA/ [40]: https://www.artima.com/images/scottMeyers.jpg [41]: http://www.awl.com/cseng/titles/0-201-92488-9/ [42]: http://www.awl.com/cseng/titles/0-201-63371-X/ [43]: http://www.awl.com/cseng/titles/0-201-74962-9/ [44]: http://www.awl.com/cseng/titles/0-201-31015-5/ [45]: http://www.awprofessional.com/esds/ [46]: http://www.artima.com/cppsource/index.html [47]: http://www.aristeia.com [48]: https://www.google.com/logos/Logo_25wht.gif [49]: https://www.google.com/ [50]: https://www.artima.com/copyright.html [51]: https://www.artima.com/privacy.html [52]: https://www.artima.com/termsofuse.html