If you’ve read ‘The Hitchhiker’s Guide to the Galaxy‘ and its sequels, you probably remember the Vogons, the incredibly ugly, disgusting, and bad-tempered aliens charged with destroying Earth to clear the path for an intergalactic highway.The Vogons’ brains, it turns out, were “originally a badly deformed, misplaced and dyspeptic liver” — and that explains their demeanor.
In this article, Jacob Matthews explains why he thinks C++ has a badly deformed, misplaced and dyspeptic liver of its own: its template system.
On other developement news, Tcl/Tk 8.4.3 and GNUstep 1.7.0 have been released.
Well worth reading. Most criticisms of C++ templates suggest object polymorphism as a solution…which would be reasonable for a dynamically typed language (e.g. Smalltalk, even Objective C since its object-model is dynamic), but which fits poorly in statically typed languages (which is why even Java is finally getting generics).
Templates are an enormously useful and powerful set of features of C++, perhaps more capable at a low level than any other programming language. As much of the work of templated code happens at compile time, you can get very good runtime performance.
However, the power comes with a price. And that price is pain. It takes a long time to grok templates all the way. Or even most of the way.
In many ways C++ is your own object language construction kit. It gives you many powerful components which you then use to build what you want. Templates are one of the categories of parts in the toolkit.
I don’t see how templates could be less complex in C++ without redesigning the language. And that redesign — call it an architectural refactoring — is something that should happen more often. I know Java and C++ would benefit greatly from a ground-up architectural refactoring.
except that, since i cannot read ML and Lisp code, i missed some little things the author explained through code snippets ๐
Even with generics, C++ is a typed language where types are checked at compile-time.
As long as your code is not shared, exported from a library or such, generics are very useful and type checking at compile-time is sufficient.
On the other hand, if your compiled code is to be shared… well, forget generics, build your own object hierarchy with interfaces (pure virtual classes), and export functions that use such interfaces. However this does not allows version compatibility, so you won’t be able to change your interfaces definitions later…
So Smalltalk or Objective-C may be a better way to go, since their “interfaces” may change (you can try to call an object method even if this object does not implement this method).
The author never provided much of a conclusion to the title. Not only that, it’s littered with technical errors.
To start with, the author completley misunderstands the notion of templates altogether. Templates are not like C macros that merely do a “copy-and-paste” strategy.
It’s also rather strange that author specifically mentions an optimization technique like constant folding, which templates are known for and even die-hard C-hackers try to mimic these days with big nests of inline functions. To make a long story short, CF lets you basically turn a big huge nest of templated code into no-ops after they’re expanded.
More ‘higher-order’ definitions like functors from ML as the author points out can communicate more intent, but they do not have the same kind of direct mapping that C++ does, which was a deliberate design decision.
Templates aren’t code generators either. The function of templates are more akin to operators. And since they’re mapped to a strongly-typed system, they aren’t “just a C++ version of Lisp macros.”
I read the first few chapters of “The Hitchhiker’s Guide to the Galaxy” and decided it was annoying. I guess I had high expectations before reading the book because it’s probably one of the most popular books of all time, but I just didn’t like it.
The author didn’t mean to belittle C++ templates. He doesn’t claim he knows a better way to do it *in C++*, or that the C++ committee should come up with one. He doesn’t even discourage you to use them.
What he *does* claim is that the next programming language aiming for generic programming should be aware that C++ templates aren’t perfect. And guess what, I happen to have a member of the C++ committee sitting nearby, and he agrees wholeheartedly.
๐
Standard C++ is the most neglected an misunderstood language of all time, however it is the most powerful and veritile of all programming languages. Not only will it not disappear anytime soon, but it will make a resounding return, because there is way too much to learn from Standard C++ and the need to have that knowledge migrated into other development systems that should have had Standard C++ language features in the first place, features that would have influenced architecture and library design.
Garen: To start with, the author completley misunderstands the notion of templates altogether. Templates are not like C macros that merely do a “copy-and-paste” strategy.
He was referring to the machine code generated by the compiler. By “copy and paste” strategy he meant that in lieu of details about the intent of the programmer, the compiler adopts a sort of “copy and paste” strategy to generating machine code from the templates. In other words, it doesn’t try to optimize much at all – it merely does a direct translation.
Garen: It’s also rather strange that author specifically mentions an optimization technique like constant folding, which templates are known for and even die-hard C-hackers try to mimic these days with big nests of inline functions. To make a long story short, CF lets you basically turn a big huge nest of templated code into no-ops after they’re expanded.
Yes, I agree.
Garen: Templates aren’t code generators either. The function of templates are more akin to operators.
This I simply do not understand. Templates *are* code generators; that is the purpose of generic programming. A function template is not a function; it is a template from which the compiler can generate functions. Same thing with class templates.
Garen: And since they’re mapped to a strongly-typed system, they aren’t “just a C++ version of Lisp macros.”
Strongly typed is not necessarily the same thing as statically typed.
Solar: He doesn’t claim he knows a better way to do it *in C++*
There is a better way to implement generics, but it is patently impossible if C++ is to retain any degree of backwards compatible with C code.
As somebody who admires C++ but doesn’t use it on a regular basis, here is my take.
Templates look like a nice idea, seem to make sense, but often seem like a lazy programming concept. I often use a familiure pattern for designing code. I want to store data (objects, usually containing fields and methods) so I write a wrapper around a list class that exports an interface that I can use to get at the data items. In C++ I would probably only ever have needed write this piece of code once, as a tempate. However over the last 4 or five years, I’ve refined the design to a simple formula that taked litterally minutes to implement. It’s also radically different from my original thoughts. If I was using templates I would probably only ever revisited the code if there was a severe speed issue. I feel like I’ve got an awful lot more out of the process having rehashed it a number of times.
As for the poster mentioning Polymorphism (and I guess implied inheritence too)… I think a well designed generic hierarchy is often more flexible. Just my opinion. Base classes and well though out parent classes often make for tighter code.. not necessarily when compared to templates, but certainly when compared to random designed stuff.
With the Standard C++ STL you have a template library. There are many generic algoritms that work with various containers through iterator class arguments. This is effective reuse of behavior because it means that each container can containin minimum behavior. Less interfaces have to be learned when the behavior is reused through generic algorithms.
Templates can be used effectively if it simplifies a set of interfaces and logically encapsulates the implementation for the set. You will probably need to use templates as well as inheritance (including multiple inheritance) and polymorphism in order to write high quality code, each tool is important.
The article can be summarized in one sentence.
“C++ compilers are more difficult to write.”
@ minkwe:
C++ code *is* difficult to write, and template error messages *are* a pain, and the concept *does* leave much to be desired.
Just reducing it to calling the author chicken doesn’t do it any justice.
The Vogons didn’t destroy the Earth to build an intergalactic highway. You make it sound like a bad thing when you phrase it like that. It was actually a hyperspace bypass.
” the compiler adopts a sort of “copy and paste” strategy to generating machine code from the templates. In other words, it doesn’t try to optimize much at all – it merely does a direct translation. ”
Compilers do a lot more than that with templates.
“This I simply do not understand. Templates *are* code generators; that is the purpose of generic programming. A function template is not a function; it is a template from which the compiler can generate functions. Same thing with class templates. ”
When I said “the function of templates” I was referring to what it is that templates do; their behaviour. Their behavior is like user-defined operators, where it is possible to encode expressions within them. That’s more sophisticated than what is typically involved with “code generators.”
The article hits on a few key points:
1) C++ templates *are* less powerful than Lisp macros. C++ cannot depend on having a compiler available at runtime, so much of the dynamic capabilities of Lisp are simply not doable within the constrants of the language.
2) C++ is less flexible than a dynamically typed language. However, proper optimizers for dynamically typed languages are very difficult to write, because method calls often have to be implemented as hash-table lookups. Further, it is hard for a JIT to generate optimized code for basic types such as ints and floats, because you can’t know whether the basic operators (which are normally method calls) could be more simply implemented as direct ASM instructions. Again, C++ can’t afford to use a large JIT (something like Psyco for Python) to create optimized static code for cases like this. In fact, when you read about Lisp code that performs just as fast as C code, it is usually because the Lisp implementation is using type-declarations, which effectively turn the language into a statically typed one.
3) The C++ template syntax is more ugly. Unfortuntately, it wasn’t designed for the kind of metaprogramming use it has gotten lately. It would have been much cleaner to use a more C++-like syntax for templates.
Thankfully, many of these problems are getting better, and the following features many be in the C++ 0x standard:
1) Typedef’ed templates will make template metafunctions that operate on types much clearer. This feature will definately be in there. The lack of it currently is considered a defect.
2) Improved preprocessor. Scoping of preprocessor macros will make them much less dangerous to use. The preprocessor actually meshes quite well with the template mechanism, which makes rather complicated tempate metafunctions rather easy to use. This feature is actively being worked on, and will most likely be in the next standard.
3) typeof() operator. This makes writing templates operating on types cleaner. This might be in the standard, it seems pretty harmless, and is already implemented in GCC and Intel C++.
4) Type inference. This is one of the cool ones. It is similar to what the author said about ML type inference. In proposed form, you could write:
auto x = 2.0f, and the compiler would automatically figure out that the type of x is ‘float’. This one is really important, because in a lot of object oriented code, type declaractions become repetitive. In Java, the common construct is common:
Object o = new Object.
Why the type declaration twice?
This might be in the standard. People seem excited about it, but it requires more compiler support, and its not like C++ isn’t hard enough to implement already.
5) Lambda. This is my little pet feature. It lets you define anonymous functions for constructs like for_each loops. So you could do:
for_each(vec.begin(), vec.end(), lambda(x){cout<<x})
Whether this gets into the standard is really iffy. There are lots semantic issues to get correct, particularly with closures and whatnot, but there is already precedence in the form of the Boost BLL and Spirit Phoenix libraries, so who knows.
The author is also wrong about compilers not optimizing C++ templates. Using a powerful high-level optimizer, heavily templated code performs the same as writing the same code in C. Just check out the Stepanov benchmark, which shows this.
Overall, I think templates are C++’s best feature. They offer a level of power and speed not seen in any other mainstream procedural or OO language. Some functional languages can match the power and speed (namely Clean and OCaml) but can’t match the low-level control. Undoubtedly, all of these languages (except maybe Common Lisp, in my opinion) are cleaner than C++, but such is the price of backwards compatibility.
@solar:
We are assuming here that you know how to write C++ code. So errors in syntax and compiler errors don’t even come into the picture. One of the main points that the author raises against C++ templates is that the compiler does not know what the intention of the programmer is. So that is not a problem of the language but a problem of the compiler.
Simply stating that C++ templates are not good because they have been done in other languages before does not hold water either. If it was that bad, people would not be using it, the author indirectly implied that everybody should be using scheme or ML or CommonLisp 8>
C++ is not perfect but it is good because it is a multiparadigm language and all the paradigms fit nicely with each other (your mileage may vary). That makes the compilers more complicated to write and sacrifices have to be made IMHO, this article is just another Java vs C vs C++ vs Scheme etc, etc articles that we know too well already.
“One of the main points that the author raises against C++ templates is that the compiler does not know what the intention of the programmer is. So that is not a problem of the language but a problem of the compiler.”
How could the compiler possibly know the intentions of the programmer? If you were looking over the shoulder of a professional C++ programmer, would you necessarily know what their intentions are?
Anyway, a lot of people (including the author) are not remembering what C++ is all about. It is an extension of C that is made for C programmers. If any of its features cause unnecessary overhead, they would not be used. See Objective-C for an example of a less strict approach.
If one wanted the cleanest, nicest looking, most featureful language, without concern for overhead, then we have Python for that. (Substitute Lisp at your preference.)
If one wanted the cleanest, nicest looking, most featureful language, without concern for overhead, then we have Python for that. (Substitute Lisp at your preference.)
I would have to substitute Lisp for that if speed is nay concern. Modern Lisp compilers can generally come fairly close to the speed of raw C WRT speed of generated code (esp. numerics — CMU CL is actually a match for Fortran when performing floating point math), where raw Python lags behind.
Ref: http://openmap.bbn.com/~kanderso/performance/
Offtopic, but as a newcomer to C++ from java, I am frustrated by the gaps in the standard library and STL, particularly with regards to the internet. In java, we can send email (smtp), receive email with pop3 or imap, retrieve a url, etc.
The C++ programmer must find a 3rd party library, evaluate it, and then learn it (only to realize that everyone uses some other library, or realize the license is too restrictive)).
parse xml — xerces (xml.apache.org)
transform xml — xalan (xml.apache.org)
xml-rpc — xmlrpc.com (3 c++ libs)
url retrieval — curl curl.haxx.se, or libwww
send email – how to choose?
receive email – how to choose?
threads — a myriad of options
Is there some website that offers advice on these things?
Just a quick shill for one of my favorite languages:
http://smarteiffel.loria.fr
class TEST[T]
creation make
feature
storage : ARRAY[T]
make is
do
create storage.with_capacity(10,0)
end
end
vs.
template <typename T>
class Test
{
public:
T *storage[10];
Test();
};
template <typename T>
Test<T>::Test()
{
for (int i = 0; i < 10; i++)
storage[i] = new T();
}
There are a lot of libraries floating around the net. Pobably the most popular is a big collection called “boost.” All of the stuff there is required to have a very liberal license that you can use commercially or personally.
For threading the boost threads library is pretty good. For something higher up at the application level for sending/receiving email – I don’t know about that, I’ve always just used my own home-brew sockets library. Boost will probably have a better one sometime soon.
>The Vogons didn’t destroy the Earth to build an
>intergalactic highway. You make it sound like a bad thing
>when you phrase it like that. It was actually a hyperspace
>bypass.
Actually, the real reason the Vogons destroyed the Earth doesn’t become apparent till later on in the series. Mind you the Radio series contradicts the Novels in theis respect anyway iirc.
( hint. It was all a cover-up concerning the Question, 6×9 and 42. )
When you compare different languages you have to look at the language definitions, the core languages, and not research and development libraries.
Java is a vendor application server and it’s library architecture is organized as an extensible specialized class framework. This is obviously a C++ framework. The Java language could just as easily used Standard C++ instead of Java as it’s core language.
We are all working with legacy platforms and now there are user mode object oriented application servers that are controlled by vendors.
Comparisons between core languages do not mean very much when most enterprises depend on the libraries, and not core langauges. Many people don’t know the difference.
I would really like to see an open source framework library that supports STANDARD C++ as the core language. Now Stroustrup says that there is not proof that frameworks are a better architecture than wrappers, however I’m not convinced of this. In the end though I just think that with Standard C++ you stand alone, and it’s possible to create something, and it’s the only language definition worth depending upon for architectural software research and developement and library construction.
I read the first few chapters of “The Hitchhiker’s Guide to the Galaxy” and decided it was annoying. I guess I had high expectations before reading the book because it’s probably one of the most popular books of all time, but I just didn’t like it.
Amen to that. Annoying characters (maybe intentional, but you can also shoot yourself in the foot intentionally) and unfunny lukewarm British humor for the most part, with a few (sadly short) hysterically funny parts (the “Mom” personality for the ship’s computer, the dolphins). It helps a lot if you play it in your mind as an episode of Futurama – the creators of that show made a way better use of the same setting and ideas