Function Template Specialization in C++
friedo writes "About.com has an excellent two-part article (Part 1, Part 2) by Eric Nagler, author of "Learning C++," about "specializing" function templates in C++. "Rather than specifying an explicit type of all of the arguments or the return value in the definition of a function, placeholders are used. This reduces the need to create and maintain multiple copies of a function for different parameter types. But sometimes, it is not possible to write a single function template that works efficiently or even correctly for every argument type. It is in these cases that function template specialization is useful.""
It's a very basic introduction to a very deep subject. Anyone who knows C++ knows the vast majority of this information.
Plus, the navigation links on the second article are broken.
For some really exciting C++, see www.gotw.ca or www.cuj.com
Those sites have great articles about templates and overloading.
In the example in part 1, this guy specializes a template function that returns the greater of the two arguments so that when two const char pointers are passed to it, it will do a lexical comparison.
If I had his code in my project, I could do this:
const char *myString = "edcba";
const char *ptrA = &myString[0];
const char *ptrB = &myString[2];
const char *greaterPtr = greater( ptrA, ptrB );
And greaterPtr == ptrA, because even though ptrB > ptrA, "edcba" > "cba" by lexical comparison.
This is a perfect example of how NOT to use the expressive power of C++. If one of the junior programmers on my project specialized a template the way he did, we'd sit him down for a remedial discussion of coding style and software maintainability.
Here's what this article says, distilled by the cynic:
If you define a binary "greater" function template, defined in terms of the operator, then it will not do the "right thing" for all types.
Wow, surprise!! But that's precisely because there is more than one "right thing" for comparison to do. What is the specification for the greater function? How could you even write one? What if we *want* greater to do pointer inequality or case-insensitive or lexicographic ordering? Distinguishing the types in your program and the operations on them is the key to an understandable program. That's one of the many reasons why overloading and template specialization are a problem.
As a technical tool to teach template specialization, okay, fine. But this is not good programming practice.
Template specialization is a nice hammer to have in your toolbox. It's worth mentioning that it's probably better, when not in an artificial example, to just use the std::string class. Do that, and the original template function works fine without specialization.
Look folks, it's called a function pointer. We've had those in "C" for a long long time, so don't act like you invented it.
In other words, some random author produced a small tutorial of some obvious aspect of C++ explained in almost any introductory book or tutorial. Why is this here?
You, sir, are an idiot.
Why is this newsworthy ? Partial specialisation of C++ templates and function templates are C++ 101 - there's nothing new or interesting here. If you're C++ coder and you don't already know about this, then you shouldn't be in your job.
Are we going to repeat this for other languages ?
The problem with C++ and swith this concept , is that it makes things quicker for the intial programmer but a DAMN site harder for a
maintenance programmer to understand.
If I see:
A var1;
B var2;
var3 = var1 + var2;
in the middle of a C++ program I have NO idea what the hell is going on unless I trawl through reams of
definitions to find out what the templates were set to and how the operator was overloaded. Sorry , but this isn't progress , its obfuscation.
Give me more lines of duplicate code with obvious definitions instead of templates and overloads everywhere.
Variable Assigment in Java
Using Perl Regular Expressions to Process text
Python Operator Overloading
Using Lisp Macros
--
CPAN rules. - Guido van Rossum
The most impressive perversion of this ilk is the Blitz numeric library. This does loop unrolling by using the template library as a term-rewriting system. The resulting code is very complex, hard to debug, and of marginal value. Blindly unrollilng loops without understanding the target architecture at the instruction level is a lose on many modern superscalar machines. Newer machines tend to do loops faster than straight-line code.
Debugging compile-time processing in C++ is tough. You can't step through the process, you can't print anything, and the compiler doesn't provides any output about what's going on. Programming at compile time has a long, sordid history (LISP macros come to mind), and C++ is an inferior environment for it anyway.
If you're using a compiler which will develop templates in-line, decide if-statements at compile time, and discard unreachable code (which includes most modern compilers), it's better to write code which works that way, rather than use template specialization.
When I call it as
excellent<crap>("specialization")
It instantiates that two-part article.
Here's why: the interpage links don't work; the text is stultifyingly redundant and verbose (a problem with all C++ documentation, sadly); the explanations are contradictory; and there is no explanation beyond handwaving for the arcanities introduced in the final example.
I've seen something like this elsewhere but it's still neat. For all the work I've done in C++, I still find I lack a huge chunk of knowledge of the language itself. I think part of it is my lack of excitement over most "learning foo" language books. I'm alot happier when things start out with code and then follow with a quick explanation and perhaps a few links to more info. The book "The Little Lisper" seemed to follow this format. It was fairly nice.
Are there any good source for C++ in this kind of format? I really like the "here's the magic" "here's why the magic works" format.
In your opinion. But this "group" is steadily growing larger and larger, and the number of critics are growing smaller, as they see the expressive power of templates.
One of the standard axioms of programming is that you know you have created a useful tool when others begin successfully using it for purposes other than that which was originally intended. Some people refuse to see templates as anything other than ways to write yet another typesafe-container-of-T. Others push a little farther into families of functions. Still others, like Alexandrescu and Veldhuizen and the entire Boost membership, have pushed on into a very different design. Automatic generation and maintenance of entire class hierarchies, to give a single example, is a big, big win.
Fine, you don't like it. Fair enough. I don't think anybody is trying to sell it as a silver bullet. But the expressive power of compile-time programming has been aptly demonstrated, and it's going to be around for a while. C++98 has some difficulties with it, because most of the techniques were discovered late in the game, almost by accident. Current proposals for C++0x contain a number of tweaks and extensions to make it easier.
This assertion is what made me respond. It's like saying, "All C programs suck," or something equally nebulous. Some machines do some loops faster than straight code under some conditions. But you won't see loop unrolling being disabled by default anytime soon, on any architecture. That decision has to be based on measurements, and testing, and experimentation, and hey- just the same thing you go through when making design decisions like whether to write C++ or assembly, and which kind of C++, and how to decompose the problem, etc, etc.
Sometimes these techniques will be appropriate, and sometimes they won't. Don't blindly condemn them all. Take a look at some of the examples where the template code produces the same assembly as the done-by-hand code.
(Until, of course, you need to do it all with more than one type at a time, then it's back to copy-and-pasting everywhere.)
You assert that it's "better" to do it your way. Do you have numbers to back this up, or is it just your opinion? (It's okay if it's an opinion, I was just curious and wanted to check.)
You cannot apply a technological solution to a sociological problem. (Edwards' Law)
(Note: this is NOT offtopic -- because this is a comment about something obvious that everyone knows except for the poster)
I did consider myself a C guru until today when I was surprised to find that if
char z[] = "\x0012345678";
then sizeof(z) is 2 (rather than 10, as I expected). It also seems that "\x00f" has size 2, but "\x00g" has size 3.
I had always believed that '\x' in a string introduced a 2-hex-digit byte constant (similar to how \0 introduces a 3-octal-digit constant).
I looked in my copy of K&R but it doesn't even mention '\x'.
Can someone fill me in on what the exact rule is, why is it like that, and when (and by whom) it was added to the C standard?
In fairness, while MC++D is indeed an interesting book for the serious C++ hacker, one should bear in mind (as the original post to this subthread pointed out) that most of the clever function stuff in it is second nature in a functional language, wherein it is obvious and a typical programmer will achieve much the same goals with far less obfuscation and much more concise code.
I've noticed that a lot of the "leading edge" C++ tools, from the STL to Loki and Boost, are pretty much trying to implement programming tools from other languages that have demonstrated value -- higher order functions, automatic resource management, high performance mathematics, complex data structures, regular expressions -- within C++. There's nothing wrong with that, of course, but the underlying techniques aren't particularly clever if you're familiar with languages that specialise in them.
Every day, as I work on a complex mathematical library written in C++, I internally groan at writing five times as many lines of code as I'd need in any major functional language because C++ has such weak support for a couple of key areas that we use all the time. The practicalities of our situation may make it the most appropriate tool we've found for the job, but looking at templates, macro hackery or cute inheritance graphs doesn't stop me wishing I could use higher order functions when working with complex mathematics...
If you disagree, post your argument. (-1, Overrated) isn't your personal censorship tool for views you don't like.