Templates Smell

(I have removed waffle, and also added additional justification.)

I have deleted what was previously said, and done my best to restate my objections to Templates in CeePlusPlus. I have temporarily put a copy of everything on the ChrisHandleysDeletions page. If you feel anything previously said is still relevant, please copy it back here ASAP.

The problem to which I believe Templates do provide a needed (but overly complex) solution is that of allowing container-like classes to be statically specialized to accept (and return) particular classes.

The very simple-to-understand reason for Templates is to implement an algorithm indifferent to a particular datatype. Creating an instance of the template would result in a code like you would get when implementing the algorithm for this particular datatype in mind. The advantage: This is what you would get with Java Generics too. The advantage of C++-like Templates are:
	template<class T,class NoiseEstimator?<T> > class Filter
	Filter(T level) : estimator(level) {}
	void filter(valarray<T> &data);
	NoiseEstimator? estimator;
The filter class implements a filter algorithm which depends on a noise estimation. Doing it like in the example above the noise estimation could be implemented in a separate class independent from the filter class. You combine these components via
	Filter<float,SimpleEstimator?> myfilter(10.0);
Thus, you can code at a very high abstract level without losing performance since the compiler brings the pieces together. Compile-time linkage is better than dynamic linking at run time since it won't waste CPU power at run time and results in higher optimizable code. Keep this in mind when reading the opinion of my predecessor below. IMHO we're programmers for writing programs for the user and not to satisfy academic arrogance.

But I strongly object to the other uses for Templates, because they can already be solved (dynamically) using standard OOP polymorphism & interfaces. Templates may well provide some (static) efficiency increase, but I do not believe this is justified when a much simpler solutions already exist - FeaturesShouldNotDuplicateOtherFeatures? (which naturally goes with AllFeaturesShouldBeSimple).

If anyone can provide a (useful but uncontrived) problem which cannot be easily solved using OOP, that would help justify Templates.

I don't think any well-rounded sane programmer wants to justify C++ templates compared with their saner equivalents in other languages. But there are many well-known uses for GenericProgramming, CodeGeneration, and HygenicSemanticMacros?, which is what C++ templates are trying to be, so many would vote for C++ templates compared with C++ without templates, and so should you. The standard library is now based on templates, you know. But each of those three subjects is a big one, and really should not be addressed on a page about C++ templates.

But a brief note: you asked for examples of "cannot". Well, that's easy enough: anything that needs to be done at compile rather than run time (that's the macro part), and that includes polymorphism with specialization occurring at compile time rather than run time.

If you, personally, don't think that matters, and that letting all such things happen at run time is fine and dandy, then you don't need such features, and you'd be happy with e.g. Smalltalk. Or, if you're committed to C++, then you should learn to love the at-compile-time offered. :-)

That's pretty much my view; C++ gives to much power (and too many choices) to the programmer in the name of efficiency, and I simply believe this is out-weighed by the complexity & associated problems that most people will have.

Assuming that the above is true, what should replace Templates? The Java people had come-up with almost exactly the same solution as I imagined - what they call Generics (see http://java.sun.com/j2se/1.5/pdf/generics-tutorial.pdf).

So Java Generics provide the alternative to Templates for statically specializing container-like classes. (Java) Generics fits well into OOP, rather than trying to duplicate statically what can already be done dynamically, and this alone should be enough to commend it - because there is simply no excuse for making something more complex than necessary (AllFeaturesShouldBeSimple).

BruceEckel's argument for Templates instead of Java Generics (see http://mindview.net/WebLog/log-0050 & http://mindview.net/WebLog/log-0051 ) is essentially based on the assumption that Latent Types are good. However, I think that LatentTypesSmell, and therefore his argument does not hold water. -- ChrisHandley

Templates and GenericProgramming are great, as an abstract idea. The problem with C++ templates in particular is exemplified by the common occurrence of single error messages that are 100 or more lines long, and essentially indecipherable (which is agreed by multiple C++ compiler implementors/experts to be unfixable, btw).

Everyone who so much as uses (never mind authors) template facilities in C++, such as STL, will sooner or later (sooner, actually) run into such messages.

The reasons for those atrocious messages is multi-fold, and interesting, but add up to a strong indictment of the design of templates in C++.

I note that there are other languages, such as CommonLisp, that have strong support for GenericProgramming (including at compile-time when needed), but do not suffer this problem, therefore it is a bug rather than a necessity in that C++ design.

I would suspect that it is largely down to C++'s insistence on having overloading (in addition to Templates!)

[See above. The LispMacro system is fully capable of including explicit assertions, run at macro expansion time, that allow reasonable diagnostics to be written.] What are you trying to say? I believe I was clear about the situation with Lisp. Oh, do you mean that something similar could be done with C++ if the language were changed? If the language were changed. (I could think of several other changes which might improve templates as well...)

It's kind of odd, since aside from this, STL and Boost and other heavy template users are one of the best things about C++. Talk about a mixed blessing!

I don't see any reason why STL couldn't be copied in Java, although I only have a cursory understanding of STL.

-- DougMerritt

You might check GenerativeProgrammingBook out. Why? It contains a very good and thorough discussion about the merits and drawbacks of C++ templates, and ways to use them.

See also GenericsVsSubtyping.

This link does not seem to have any relevance, since I already implicitly assumed that the level of Generics provided by Java is a VeryGoodThing?, and that link simply says that CeePlusPlus Templates & Java Generics are very useful.

My contention was that Templates are overly complex compared to Java Generics, for the useful problems that they solve.

I haven't learned JavaGenerics yet, but they'd be idiots if they didn't learn from C++ mistakes, after all these years, so I certainly would expect it to be better. There's no excuse for it to not be better. Or to put it the other way around, they have the unfair advantage of designing them 15 years later. :-)

C++ Templates are one of the most powerful features of the language. They provide for compile-time polymorphism rather than the run-time polymorphism seen with interfaces and inheritance. This polymorphism is actually very powerful, because any type that meets the syntactic requirements of a template can be used as a parameter, without having to explicitly declare an interface. This makes it possible to use templates with classes that were designed independently.

As well as the GenericProgramming allowed by the compile-time polymorphism of C++ templates, they also allow for code generation and meta-programming, and even some simple reflection - if I can do this, use this algorithm, else use that one.

The big downside is the compile time dependencies - since the compiler needs to see the source code for the templates when compiling every bit of code that uses it, this can make compiles take a long time. The error message problem mentioned earlier is less of a problem with newer compilers.

In general, I would not say that TemplatesSmell. However, like any powerful feature (such as inheritance), they can be misused.

-- AnthonyWilliams

For a beautiful application of C++ templates see http://www2.imm.dtu.dk/~km/FADBAD/, I recently used the ideas there to implement a photogrammetry tool that required computing the 2nd derivative of a function computed by a couple of thousand lines of C++ code. I'd love to know how to implement such a thing without templates.

Templates provide compile time reflection. See TemplateMetafunctionHasFunction.

C++ is one of the most expressive languages I have ever worked with. Problem is, it's got Tourette's Syndrome or something because it often just barks at me and curses. I should hope the design of the C++ language is the problem here and not the features it sports, namely templates. Template specialization and partial specialization are dazzling. Having a template class extend from a virtual base class is lovely magic. If you allow yourself to use macros, well now things can get interesting.

I agree, the error messages are ridiculous and difficult to read. The other thing I hate is, once you jump into the templates boat, you start using them everywhere and unless your compiler vendor has worthwhile PrecompiledHeader? features, your build times can become dismally slow. In general, my experience with test driven development is hellish in C++ when I use the bells and whistles.

I spent 9 months porting Java Fit to C++, (which originally took a weekend for the Java authors to write?). It was a painful experience, but that was more due to the lack of standard unicode and regular expression libraries than it was C++ language issues. I was curious if I could faithfully reproduce the reflection features used in Java Fit using templates and macros. I feel like I succeeded, here are some of the more interesting language features I used:

Perhaps the thing I hate the most when reading this features list is the gnawing feeling that I have somehow stolen what I wanted away from C++ rather than it giving it up to me freely. Couple that with some of the tortured hacks needed to get the code to build on VC++ 6.0, Borland C++ Builder 6.0, Solaris CC, and GCC 3.3 (and higher), and I feel like I just pulled off a bank heist. Still, I feel like mine are language design and standard library issues and could be ironed out by language designers without losing expressiveness.

If you are interested in checking out what I have done, please visit http://ceefit.woldrich.com or http://fit.c2.com.

-- DavidWoldrich

As pointed out, C++ templates often produce eye-achingly long error messages, because in the general case the compiler doesn't know which part of the template you may be interested in seeing. However, in most cases there are several bits you aren't interested in seeing. For example, you want to see:


 basic_string< char, char_traits<char>, allocator<char> > 
This is easily done by using something like StlFilt to remove the common stuff that you don't want to see because you haven't used any custom allocators, etc. As far as I can see there is no reason why a standard conforming compiler couldn't do this anyway. You would, of course, need a switch to get the full message for the rare occurrences when you do use a custom allocator.

CategoryCppTemplates CategoryCpp CategoryCodeSmell

View edit of September 27, 2014 or FindPage with title or text search