Slashdot Mirror


C++ Templates: The Complete Guide

nellardo writes "The book C++ Templates: The Complete Guide, by Vandevoorde and Josuttis, Addison-Wesley 2003, is an authoritative treatment of exactly what it claims: the template mechanism of C++. If you are a C++ programmer, you should have this book on your shelf. If you aren't a C++ programmer, move along -- this book is highly specific to C++, and won't be much help in understanding the template mechanisms of other languages. Of course, if you aren't a C++ programmer, you probably wouldn't even give this book a second glance in the first place." Read on for the rest of Brook's review. C++ Templates: The Complete Guide author David Vandevoorde & Nicolai M. Josuttis pages 528 publisher Addison Wesley rating 10 for C++ programmers, 0 for anyone else. reviewer Brook Conner ISBN 0201734842 summary A thorough, exhaustively complete treatment of a complex subject. An essential reference for C++ programmers and a lengthy and boring book for anyone else.

The C++ programming language is widely regarded as a good systems programming language, albeit a complex one fraught with low-level details and issues (though arguably this is what makes it good for certain kinds of systems programming). For perhaps a decade now, C++ has had a template mechanism - in programming language circles, it might more properly be called a form of parametric polymorphism. The template mechanism, like many other forms of parametric polymorphism, is potentially extremely powerful, but the complexity of C++ makes it tough to thoroughly master. That's where this book comes in.

Most likely, an experienced C++ programmer has at least used templates. If nothing else, use of the Standard Template Library (or STL) requires at least knowledge of how to use templates. If you use C++ enough to care about templates, you probably know what they are, at least roughly, and if you don't, this isn't the book from which to learn about them. It very clearly requires (and explicitly states in the introduction) that you need to know C++ before making effective use of the book.

Designing template classes, however, is another kettle of fish, and if you're in a position where you're building template classes for someone else to use, you probably need this book. Unless, like the book's authors, you moderate comp.lang.c++.moderated. If you are such a super C++ guru, you may still find this book useful - it is a truly stupendous catalog of the capabilities and subtleties of C++ templates. If nothing else, you'll find examples for well nigh every use to which you are likely to put C++ templates.

The book's strengths, then, are its authoritative and exhaustive detail. On the downside, its examples are dry and flavorless. Perhaps this is intentional, as a way to suggest how some feature can be used in a variety of situations. I prefer a combination of specific, concrete examples, followed by a generic example. The specifics motivate the need for a capability, while the generic showcases the broad, interrelated aspects of the capability. The authors didn't follow that approach. I would suspect this comes in part from their mutual roles in C++ standards bodies - a specific example could be seen as too limiting, and so were left out.

Another drawback, to my thinking, is its resolute focus on C++ to the exclusion of all other languages. Don't get me wrong - I read the title, and it's a C++ book, so I don't expect it to teach me Scheme, much less Haskell. However, I think the complexities of C++ templates might have been easier to tackle and understand with at least pointers to other ways it could have been (and has been) done. If nothing else, citations of alternative approaches would be a useful source for the motivated reader. As it is, it doesn't even deal with differences between C++ implementations - it doesn't even list GCC in the index.

All in all, though, C++ Templates: The Complete Guide is exactly what it claims to be. It's an in-depth treatment of C++ templates and how they work. It isn't a cookbook for practical applications, nor is it a guide to further in-depth exploration of parametric polymorphism. But it is definitely a handy reference for the working C++ programmer to have on her shelf. If you're a working C++ programmer, I'd recommend it. If you aren't, you might want to pass on this one.

You can purchase C++ Templates: The Complete Guide from bn.com. Slashdot welcomes readers' book reviews -- to see your own review here, read the book review guidelines, then visit the submission page.

23 of 371 comments (clear)

  1. Re:Are templates always necessary? by tomhudson · · Score: 4, Insightful

    But then you loose the flexibility of multiple inheritance if everything ultimately has a single parent. It's always going to be a trade-off. If there was "one right way" to do everything, we'd all be out of jobs within the next decade :-)

  2. Bloat by warmcat · · Score: 2, Insightful

    I have used C+ for several years, and love its abilities to model layers of belongingness with its OO principles: but I assessed templates as evil and have never used them. My understanding is that the template mechanism is like a super #define, that is, the compiler spawns multiple implementations of templated classes.

    The seemed to me a recipe for bloat/cache thrashing/ugliness. I did not see bloat addressed in the review. In my reactionary way I continue to believe my prejudices.

    Does anyone who has used templates have anything to say about templates and bloat?

    1. Re:Bloat by Buck2 · · Score: 5, Insightful

      I'm just throwing this out there but anyone that knows any better please feel free to present an argument:

      We use the blitz++ library in our laboratory due to benchmark findings that it is an extraordinarily fast package of matrix-type operations. It has been repeatedly argued that the speed of the library is due to the fact that it is entirely (I believe) implemented with templates.

      If you'd like to read some hairy code ... check out blitz++. :) And the errors you can get when compiling are simply astounding. AFAICT, though, it's damn fast.

      So, no, templates don't necessarily lead to bloating/ugliness/slowdowns/whatever if done properly.

      --

      As my father lik@(munch munch)... ....
    2. Re:Bloat by Malc · · Score: 4, Insightful

      I use templates with virtually every class and method I write: the STL. I couldn't live without it. It simplifies my development efforts, and helps me produce C++ solutions faster and with greater reliability. So far none of the applications have needed performance tuning. I'm sure there are situations where it is in appropriate, just not in my circles. I shudder when I think back to my C++ days prior to using the STL. So, I'm all for it and the ditching of the pre-processor and basing things on void*.

    3. Re:Bloat by Anonymous Coward · · Score: 1, Insightful

      Templates are an organizational tool, not an optimization tool. They give the developer parametric polymorphism at design time, so she can deal with one "customizable" class instead of 20 slight modifications. The code size is correspondingly shrunk.

      This organizational tool comes at a price: the compiler expands each type as it would a #define function, so while your code size is nice and small, easy to read, your image size can really bloat. Also, I haven't seen a symbolic debugger work perfectly with templates.

      In my experience, templates are a great refactoring tool when you can afford a larger footprint. Otherwise, they are cumbersome and unnecessary. I guess it really depends on your particular application and target platform... developer experience should be taken into account as well.

    4. Re:Bloat by Gortbusters.org · · Score: 3, Insightful

      True that. Not using the STL is like saying you will rewrite the entire Java API for your application, save the base Object.

      Some people say they use the good ole void* instead of a template. Those people sometimes do memory debugging for months.

      --
      --------
      Free your mind.
    5. Re:Bloat by warmcat · · Score: 2, Insightful
      If you're a C++ programmer and don't use templates, you're not doing your job.
      ...
      I would certainly never hire a "C++ developer" that don't at the very least have thorough experience with the STL, and preferrably understand how to write (and when to write) templates

      As it happens most of my work is done down near the hardware. So those peksy issues of the relationship of compiled code to the hardware - which cut directly across things like having 24 copies of each method in a class because the class is templated across 24 types - are very important.

      Sure for some types of work the longevity and conciseness of the code is more important than the efficiency, I understand that. And in those types of work you can basically forget that you are running on real hardware with real limitations, since time and memory will 'stretch' for you. But just like it sounds you wouldn't hire me, I don't think for my kind of work I would hire you :-)

    6. Re:Bloat by IWannaBeAnAC · · Score: 2, Insightful
      Removing parts of the library might be a good idea (IOStreams, for example, is pretty slow, for example), and may be desirable in some cases, but the language features you mentioned should not affect performance. One of the design principles (not always kept, mind you) of C++ is that you don't pay for what you don't use.

      If you don't use multiple inheritance, then you don't suffer a performance drop. If you don't use exceptions, you don't suffer a performance drop. Templates, namespaces, and new-style casts all provide the programmer with more tools, and have no intrinsic performance issues while allowing more flexibility of program design.

      In other words, the reason why embedded C++ is so disparaged in the mainstream C++ community is that the subset of C++ it implements is based more around what is easy for compiler writers to implement, rather than what is desirable for a programmer in an embedded environment.

      In some forms of template programming, with some compilers, there is a bloat problem. For the most part, this has been fixed by better compilers (recognising when two different instantiations produce equivalent code) and better design.

  3. Re:Are templates always necessary? by FortKnox · · Score: 5, Insightful

    Well, I'm going against my grain here (being a Java lover), but templates mean that you ensure cast.

    For example, I make a stack in C++:
    Stack bleh<int> = new Stack();
    int i = 1;
    bleh.push( i );
    (excuse my syntax, I havne't C++'ed in a few years) and I have a stack full of ints.
    If i use a java container:
    Stack javaStack = new Stack();
    javaStack.push( new Integer( 12 ) );
    I lose cast. If I pop from C++'s bleh, I'm guaranteed to have an int. If I pop from Java's javaStack, I'm getting a java.lang.Object. I have to force cast and have a chance of a runtime exception.

    That is one major reason why templates are a good thing.

    --
    Good quote, too many chars. Seriously, the slashdot 120 char limit sucks!
  4. Only when misused by DreadSpoon · · Score: 2, Insightful

    Templates are only bloat when misused. In many cases, your options are to write a template, or cut-and-paste then modify a class/function over and over. You can also write classes that only have template members, so if most of a class is the exact same no matter the data type, you're fine. Templates also let you do things you simply can't do in this low level of a language otherwise (and many high level languages also don't allow) - take a look at what the BOOST library does. There comes a point when you have speed/efficiency/code-size vs. taking 6 years or 6 weeks to code something, and with today's hardware, the later is usually the best choice. Also, templates can be used to generate data, not just code, so where you might have before needed a function call in order to compute a value, a template could turn it into the actual value at compile-time (look at how modern games use templates to generate sin/cos/tan/etc. values for constant inputs).

  5. Re:Are templates always necessary? by truth_revealed · · Score: 4, Insightful

    Templates only seem to be a necessary evil in OO languages that don't ultimately inherit all objects from one object.

    This is a naive view that circa 1992 C++ collection class designers used to share. The OO-container strategy was proven to be slow and not type-safe. The designer of the C++ Standard Template Library (STL) Stepanov does not even believe in OO programming - he calls OO a hoax. I personally would not go that far, but I appreciate that OO and generics are completely independent concepts. Furthermore, an STL map or vector working on types directly is much more space efficient than any OO container-based approach because each object contained does not require OO overhead. Indeed, native types (ints, doubles, etc) in vectors can be nearly as efficiently stored and accessed under STL as would C style arrays. No need for awkward casting or unnecessary and slow boxing/unboxing. To sumamrize, C++ templates and the STL fit in perfectly with the C++'s "zero overhead" principle.

  6. No bloat if you design correctly. by Chemisor · · Score: 5, Insightful

    Just like macros can bloat your code, so can templates. If you put "real" code in templates, it will be duplicated; however, consider that you would have probably had to write it anyway, and having template instances is FAR better than having cut-n-paste code. STL instances can get pretty big because they have lots of memory management code in there and type-specific operations; this is good because it gives you type safety and proper element assignments. You can implement it another way, but you have to sacrifice something. Either it is type safety (like Java does with its containers), or correct element handling (escuse the shameless plug for my own ustl library).

  7. No portability info? Bummer. by baxissimo · · Score: 4, Insightful
    As it is, it doesn't even deal with differences between C++ implementations - it doesn't even list GCC in the index.

    That's too bad, because 9 out of 10 times when I've had troubles with templates it's because of differences between C++ implementations. Beautiful, well thought out, intricate standards-compliant examples are useless if I can't actually get them to compile with my real-world compiler!

    The book I'm looking for is the one that gives me real-world recipes for getting around bone-headded compilers. For example, there are at least 3 different ways to declare templatized friend functions depending on the compiler. Only one is correct according to the standard, but the standard isn't worth a whole lot to me today if the compilers I'm stuck using don't follow it. And likewise, an advanced templates book isn't of much use to me today if the examples won't compile on my compilers.

  8. Re:Are templates always necessary? by Anonymous Coward · · Score: 1, Insightful

    Exactly. If there is one thing Java lacks that is more strong typing in its Collections classes. The collections classes are arguably one of the best things that have happened to Java in a long time, but the fact that you have to use casting so often really leaves a bad taste. C++ templates definatelty rule in that area (coupled with operator over-riding, which I also think is super cool).

  9. Re:What about Java/C++ developers by Anonymous Coward · · Score: 1, Insightful

    Whoever came up with the 'templates' in Java understood less than half of what templates are actually useful for. The Java version only addresses the 'cast' situation when retrieving objects from a collection (like the Stack example you'll find elsewhere in this discussion). No provision was made for using templates for policy and that's where the real power of C++ templates is. Other's have mentioned it, but pick up the Alexandrescu book to understand. You'll be amazed.

  10. Extensive template use is dangerous by mcgroarty · · Score: 4, Insightful
    Despite C++ templates having been around for quite some time, development environments still haven't caught up.

    Debugging heavily templatized code is thoroughly nasty. Names are mangled beyond recognition for anyone not using a 500 column display or lots of scroll bars. Stepping through code in the debugger often yields senseless results -- you often cannot see the source for the instructions being generated without manually tracing through the headers and looking for every overload and template body declaration. Templates thorougly ambiguate linker symbols. Templates slow compiles to a crawl, often adding tens or hundreds of thousands of lines to every inclusion of a given header in order to define the types it uses. With subtly improper use, templates can bloat code size astronimically and create horrendous execution bloat.

    I don't know how many weeks I've lost to helping others debug or rewrite their code because they thought they would do something "clever" with templates and they ended up creating a maze. And bringing in third-party code with templatized interfaces has frequently required more time to debug and adapt than it would have taken to create the code anew.

    If you're going to use templates, stick to simple container classes for now. Anything else should be considered theoretical research until the tools catch up. Let me repeat: development tools HAVE NOT CAUGHT UP WITH C++ TEMPLATES. There is no debugger available which makes templates as transparent as normal code, inline functions or even #defines.

    And please save your first forray into templates for private projects. Don't inject your template experiments into code others are trying to use!

  11. Re:What I want explained to me... by rudedog · · Score: 3, Insightful

    about templates is why this doesn't work:

    main.cpp has never seen the implementation detials of the Foo constructor or the getFoo method, because g++ compiles each compilation unit in isolation. Conversely, no real code actually got generated when g++ compiled Foo.cpp, because that didn't contain a particular instantiation of a template, only the generic template definition.

    The typical idiom is to put a '#include "Foo.cpp"' at the bottom of Foo.h. Then, when g++ compiles main.cpp, it will have seen the template's implementation in order to turn it into code.

    This actually is explained in the book in question (chapter 6, I think).

  12. Re:What I want explained to me... by Lethyos · · Score: 2, Insightful

    *nod*

    You can get round this by putting the entire template definition in the header file, which may lead to massive code bloat if your linker doesn't combine all the multiple definitions.

    That is essentially #include "Foo.cpp", which is insanely ugly. Come to think of it, it's been so long since I last tried to use that I cannot remember exactly what I was trying to do with it -- except that it would have made things a lot easier. :-)

    As far as I can recall (without getting into specifics), I had a limited number of classes that while they were similar in nature, did not necessarily lend themselves to inheritance from a super class. Overloaded operators were present to make them act appropriately in an encapsulation (that would be class Foo).

    A more basic example would be a graph implementation. The first time I wanted to do this was for course work. I tried creating a generic node object that could take any types for the key and data, and this is how I approached it (should be fine especially since the node class would have no need to manupulate the data).

    Professor said that this approach created ambiguities, but with a concrete instantiation, I thought the compiler/linker would be able to work it out. Oh well.

    I like how Java has an "Object" superclass to everything. That's solves this issue. As for C++, I guess it's not so bad to have an "Object" class in your project.

    --
    Why bother.
  13. Re:Are templates always necessary? by Anonymous Coward · · Score: 1, Insightful

    Typesafe Collections are a good thing, agreed. But are they a big deal? I can't recall a bug thats bit me in the past three years with the Java collection of Objects model but I recall vividly the pain of developin with C++ templates, the bloating in apps, slow builds, and painful debugging.

  14. Re:3D Math by Minna+Kirai · · Score: 2, Insightful

    It is by no means a "kludge". The intended use of a tool is never a kludge, even if some people find it personally unintuitive. (The only kludgey thing in that article was the extra magic needed to convince MS VC++ to deal with templates sanely)

    The goal of adding templates to C++ was to provide the same power macros provided to C, but as part of the language, rather than a preprocessor to it. That way, they can be typesafe, produce better error messages, and be more flexible (since templates live inside of namespaces, unlike macros which exist at the parser level).

    C programmers often performed fast math evaluations with macros, so replacing them with templates is simply a natural step.

    However, looking at templates from an entirely different perspective- it is possible to reasonably classify most all uses of templates as "kludges".

    Why? Because they are often used to force an evaluation to happen at compile-time, rather than runtime. But, if compilers made full use of the static program information that is present during compilation, they could determine that many conditional checks are often tautologies, and elminate them from the output code.

    The reason C++ compilers can't usually make these throughout checks is because of backwards compatibility- to support interoperation with other programming languages, individual C++ files are compiled independently and then linked together by a stupider program. The linker has little knowledge of the static program elements, and less ability to modify the output code. So many potentially useful optimizations are impossible- unless the programmer uses something like templates to force them to occur.

    So, from that perspective, it can be argued that nearly every template is a kludge- a workaround for the legacy compiler/linker split. (Many uses of macros were a similar kludge- a way to force an expression to be computed inline, rather than spending a function dispatch on it)

  15. Re:Are templates always necessary? by ucblockhead · · Score: 3, Insightful
    The difference becomes clear if you accidently try to push something else on the stack. If you try to push a string onto the STL stack, you get a compile error. If you try to do the same to the Java stack, you don't find out until runtime, when you do the cast.


    In other words, you better hope that your testing is good and that the bug that causes a string to get put on the stack doesn't only appear in a rare set of conditions.

    --
    The cake is a pie
  16. Re:Yes. Templates are not macros by Tiny+Elvis · · Score: 2, Insightful

    What problems of Lisp (Common Lisp?) macros are you talking about?

  17. Re:Are templates always necessary? by jaoswald · · Score: 2, Insightful

    Look, if you are dealing with a team that has not divided responsibility for design decisions according to a clear system, then that is your real problem, not the lack of compile-time diagnostics. You're also going to get huge numbers of bugs that the compiler *won't* catch.

    The problem with C++ in particular is that it is a bondage-and-discipline language. Everyone on your team has to figure out in advance what chains and barriers are going to be put up in order to allow the problem to be solved within the C++ language.

    In a dynamic language, you *choose* what barriers to put in place in order to maintain safety. You aren't forced to put a lot of barriers up that will never be needed.

    Also, what people miss is that in Lisp, for instance, a run-time error usually puts you in an interactive debug environment, allowing you to make changes to the program (still alive) using the full power of the Lisp language, and the full resources of your program, in order to find the problem, fix it, and continue execution. This is just now coming to pass in the C++ world, with incremental compilation, etc., but Lisp programmers have had this for decades. When you are developing, you will find the errors, and for production, you can write error handlers that catch these various conditions, log them as appropriate, and specify how execution should continue.

    The strategies you use with a dynamic language to prevent and deal with these kinds of problems are different than with static languages like C++. The strategies aren't better or worse, just different. What you gain with dynamic languages is a kind of flexibility that allows you to attack the problem, not the language, and to do so with a maximum payoff for programmer effort. What you gain with C++ is the ability to catch certain types of errors, which aren't really that common, especially as intellisense-type tools are becoming much more widespread. Much of the time, when the compiler complains about type mismatches, you add a cast. The language is forcing you to explain yourself again, not really pointing out a logic error in your program.

    The real problems that programmers face are errors of logic, which no language can address, and the ability to express the desired operation, which dynamic languages make much easier than static languages, because they don't require as much unnecessary or redundant description.