Function Template Specialization in C++ 89
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.""
Why is this here? (Score:3, Informative)
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.
Re:Why is this here? (Score:5, Interesting)
Good question. I don't know why.
Frankly, if you want to see what templates and partial specialization can really do, go get Andrei Alexandrescu's book Modern C++ Design, from the In-Depth series (which I've posted on before, somewhere). As others have said before, the third chapter alone is worth the price of the book, just for what it will do for your understanding of specializations.
I would post a link to Alexandrescu's site, but he's recently done something to it which causes mozilla to either crash instantly or hang indefinitely, requiring a kill -KILL in a console. Looks like either Java or frames.
Re:Why is this here? (Score:2)
I second that recommendation. Any one chapter is worth the price of the book. I thought I was exploiting templates to the point of torturing my compiler. Boy, was I wrong!
Re:Why is this here? (Score:5, Informative)
Agreed. A mind-blowing book, it will challenge your ideas about how to code.
It's about more than just C++ templates; although its use of templates is revolutionary, the more general and important message of the book is about designing small, re-usable pieces of code that interact gracefully with each other (and to the extent possible, interact at compile-time rather than run-time). These ideas can, in theory, be applied to any langauge that supports class typing; in practice I've used in in pre-generics Java to a small (and non-revolutionary) extent.
If you program in any significant way in C++, you owe it to yourself to get the book, if for no other reason than to re-experience that sense of wonder you felt when you compiled your first program.
Re:Why is this here? (Score:2, Insightful)
How pretentious of you to assume this. Most people don't even know how write a template function let alone write a single function template that works for every argument type. I found this artical very informative and definitely worth the read.
Re:Why is this here? (Score:2, Insightful)
But hey, would you expect any less from
Re:Why is this here? (Score:1)
That's great. I would find an article on some not-basic-but-also-not-advanced-lisp worth the read and informative. That's because I only know a bit of lisp. I'm glad the article was published, and I would recommend it to my friends and neighbors who know a bit of C++.
But it's not
Re:Why is this here? (Score:2)
C++ is not synonymous with STL templates...It is a feature the use of which is not mandatory.
Re:Why is this here? (Score:2)
In any case, if you don't know how templates work, you only know a little bit about C++. Templates are a language feature, not a library, and most serious development can benefit greatly from using templates. I would assert that if no part of your application uses templates (STL or otherwise), you should be using C instead.
Re:Why is this here? (Score:2)
"I would assert that if no part of your application uses templates (STL or otherwise), you should be using C instead."
Oh Jesus you didn't just say that and mean it did you?
Re:Why is this here? (Score:2)
I would assert that if no part of your application uses templates (STL or otherwise), you should be using C instead.
Uhhh, why? As punishment for not learning how to use all the features of C++?
Even without templates, C++ can save you some code bloat and exhaustive logic processing over plain C.
Re:Why is this here? (Score:1)
As a widespread feature, templates are a relatively new addition to C++. The first C++ complier I ever used (in the early 90's) did not support them (or exception handling either). Discussion of function and class templates take up all of 12 pages in the C++ ARM.
Point being, there are people with several years of C++ development experience who haven't worked much with templates. You kids who grew up with C++ probab
Re:Why is this here? (Score:2)
Re:Why is this here? (Score:2, Interesting)
I would put template specialization in the same category as using a value as a template argument instead of a type ie. template. It is a feature that is very useful in some instances, but is rarely used even when useful and isn't taught in the majority of c++ classes.
Parametric polymophism. (Score:2, Insightful)
Re:Parametric polymophism. (Score:2, Funny)
Re:Parametric polymophism. (Score:1)
Re:Parametric polymophism. (Score:1)
Re:Parametric polymophism. (Score:3, Informative)
If a function is a first class object, then you can (a) queue it for later execution, (b) manage an ordered list of functions for execution, (c) partially qualify the parameters for later execution, with the remainder specified at call (i.e. dispatch) time. Read up on functors some time.
Re:Hi fallutin' OO zealots!!! (Score:3, Informative)
A functor is far more than a "function pointer".
A functor lets you fix none, all, or some of the parameters that are to be passed to the function via the pointer to it. This has practial applications. For example, an editor with an "undo" function that dispatches based on queued functors of edit operations, can also implement the "undo" by mapping that queue of functors to a nre que
Re:Hi fallutin' OO zealots!!! (Score:2)
The grandparent was talking C.
>You really should read Modern C++ Design to develop an appreciation for these techniques. They aren't obvious at first.
I agree on the book suggestion. However, I disagree on the non-obviousness and generally oppose any techniques that are not obvious to developers.
Re:Hi fallutin' OO zealots!!! (Score:2)
Excepting the tiny share of geniuses, most things are non-obvious to most persons, at first. I suspect, for instance, that I was surprised when I was first told that objects, regardless of mass, fall at the same rate.
The use of classes, and inheiritance to specialize code was "non-obvious" to me when I first encountered it. After reading about it, however, understanding quickly dawned, and I
But obvious (or not) to whom? (Score:3, Insightful)
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 n
Re:Hi fallutin' OO zealots!!! (Score:2)
This is a real world example, incidentally.
Re:Parametric polymophism. (Score:1)
Re:Parametric polymophism. (Score:2)
Re:Parametric polymophism. (Score:3, Insightful)
Not surprising, since the two-level nature of C++, via templates is more of an accident rather than a design. There are better languages out there that support these facilities in a clean fashion.
Nevertheless, these are extremely useful and poweful techniques. Every language has it's "dark and ugly" side -- think about the macro hackery you need to support parallel arrays in C.
Re:Parametric polymophism. (Score:1)
Re:Parametric polymophism. (Score:1, Flamebait)
Seriously, go and read Modern C++ design, because that's the least of the syntactic salt of C++ templates. It may be a powerful feature, but it's so encrusted with syntactic baggage that it often obscures the actual logic of the program. For the absurd conclusion to the horrors of template syntax, check out the Lo
Re:Parametric polymophism. (Score:1)
(Score:2, Flamebait)
when you can do
(Score:5, Informative)
Horrible example (Score:1)
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
Re:Horrible example (Score:4, Insightful)
Oh, I wholeheartedly disagree!
Any junior programmer I encountered who was interested in generic programming would get my greatest support, and gentle guidance. I might not permit his initial attempts in production code, but I wouldn't stifle his interest either. How the hell else is a programmer supposed to mature their art?
Yes, it's real easy to fuck yourself up a million ways from Sunday, and none of them good, when you try to exploit a language mechanism that provides a two level language, with selective binding, but the power is immense. Just look at the use of C++ template metaprogramming for compile-time optimization -- it solves the cost of abstraction problem.
The syntax sucks, of course, and that makes it hard to comprehend, but that's to be expected when the Turing completeness of a language facility comes not by design, but by accident.
Ideally, in any project architects define the desirable coding abstractions, senior programmers implement the support for them, and more junior programmers code using them -- there is no more need for a junior programmer to understand template arcana than there is for them to understand the building of glibc (which is a either a horrid abuse of make, or a beautiful hack, depending on your point of view -- xargs is your friend).
When you strive to reducing all the code your team writes to that understandable by the lowest common denominator of skill available, you compress the scale of productivity exhibited by your team members greatly. Given that coding productivities can vary by an order of magnitude within a team (some have said, this really isn't something you want to do.
Instead you should build layers of abstraction, including meta languages within your code, giving the difficult implementations to the senior members, and the simpler ones (considering also the abstractions you've built) to more junior ones.
Part of the problem with your complaint is that you continue to see pointers to NUL-terminated character arrays instead of strings, right down to your pseudo-Hungarian notation. The whole idea is not to compare pointers, but strings, with the pointer implementation of a handle to the first character of the string a string implementation detail, ideally hidden.
Re:Horrible example (Score:1)
I would say the problem is that you (and the author of the article) see a pointer to a NULL-terminated character arrays as being the same as a strin
Re:Horrible example (Score:2)
Re:Horrible example (Score:3, Insightful)
I suppose if I were to implement the template, I'd have a greater member function that throws an exception when passed a pointer, with a partial specialization that works for pointers to chars
Re:Horrible example (Score:2)
*cough* void* *cough*.
I reiterate that char * is idiomatically used to represent the base of a C-style string, and is the type of string literals (which, admitedly, can be converted to std::string, easily enough, but then you run into exactly the problem to which y
Re:Horrible example (Score:1)
Bad idea (Score:2)
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
Other ways to do it (Score:1)
Huh, where's the beef... (Score:2)
why is this newsworthy ? (Score:1, Flamebait)
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 ?
Re:why is this newsworthy ? (Score:2, Informative)
Re:why is this newsworthy ? (Score:2)
Wow. Active Perl 5.6 is now Active Perl 5.8, and supports Threads let's put the incrementally supported features on the front page even though it doesn't apply to any other Perl installation
It just gets even more convoluted (Score:4, Insightful)
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.
Re:It just gets even more convoluted (Score:2)
A var1;
B var2;
add(var1, var2, &var3);
Because now you know
Seriously, operator overloading is just syntactic sugar for a function call: it's no more and no less obfuscated.
Re:It just gets even more convoluted (Score:3, Insightful)
class foobar var1;
class wibble var2;
var3 = concatenateNames(&var1, &var2);
Or something like that. If people only ever used operators for their namesake operations there wouldn't be a problem but how often have you seen
code where + is overloaded to do all sorts of different operations depending on the STATE of what gets passed to it, never mind
the actual types that get passed.
"operator overloading is just syntactic sugar for a function call: it's no more
Re:It just gets even more convoluted (Score:1)
Yes, of course programmers can make bad choices. But forcing someone to provide a name instead of an operator does not prevent this -- the developer could still choose a lousy function name if they want
Re:It just gets even more convoluted (Score:1)
Or you could whip open your IDE and click go-to-definition, or run the debugger and go step-into.
Re:It just gets even more convoluted (Score:2)
"open your IDE and click go-to-definition,"
Err , my IDE here is vi and grep. The debugger is dbx. Need I say more?
Re:It just gets even more convoluted (Score:2, Insightful)
True, but in my experience operator overloading is more subject to abuse. With a function, the devloper has to give it a name, and the potential namespace is much larger than the operator namespace.
Re:It just gets even more convoluted (Score:3, Insightful)
The counter to your objection is that if you don't understand the types in a program, you've got no business messing with obj
Re:It just gets even more convoluted (Score:2)
Its not a case of understanding them , its a case of knowing what they are.
"many so-called "programmers" lack the skill to do this and get miffed."
Given that to write any program you have to understand the higher level abstraction of it as well as the low level details of how to
accomplish the task I have to disagree. If anything the higher level abstraction is the easy bit. For example any idiot can use stacks or
queues from the STL in C++, very
Upcoming "Developers" Headlines: (Score:3, Funny)
Using Perl Regular Expressions to Process text
Python Operator Overloading
Using Lisp Macros
Re:Upcoming "Developers" Headlines: (Score:1)
Is this even correct C++? (Score:1)
Re:Is this even correct C++? (Score:2)
Re:Is this even correct C++? (Score:1)
Re:Is this even correct C++? (Score:2)
You are correct that partial specialization does not exist for function templates, only class templates, of course, but that doesn't mean the syntax can't be considered. Perhaps I should have been clearer.
If partial function template specialization were supported via the intuative syntax, both would b
Re:Is this even correct C++? (Score:1)
Re:Is this even correct C++? (Score:3, Insightful)
WQe are not talking about the same thing. Consider the class template:
template <typename T, typename U> class X { ... };
This can be partially specialised thus:
template <typename U> class X<int, U> { ... };
and fully thus:
class
Re:Is this even correct C++? (Score:1)
Re:Is this even correct C++? (Score:2)
Thanks for taking the time to follow up. I am equally guilty of having forgotten about the second form of template specialization you described, that is, where some template formal types are related to others.
You have to be careful with functions with the term specialization. The word is overloaded (no pun intended). It can mean (1) template specializatio
Re:Is this even correct C++? (Score:1)
Another marginal C++ feature (Score:4, Insightful)
The most impressive perversion of this ilk is the Blitz numeric library [oonumerics.org]. 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.
I mostly disagree (Score:3, Interesting)
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.
Re:I mostly disagree (Score:2)
PL/I had compile-time programmability. That didn't help.
In LISP, macros became so bloated that Scheme had to be invented to strip the language down. But it was too late.
In the early days of UNIX, the M4 macro processor was popular. (It lives on as the horrible front end to Sendmail.)
Term-rewriting systems were a fad in the mid 1980s (remember Prolog?). Didn't help.
The trouble with compile-time programmability is lac
Re:I mostly disagree (Score:2)
While agree with much of what you say, I think source code level optimisation still has its place. We (an office who write high performance maths libraries) recently reviewed a document written by AMD, on how to optimise performance on their recent chips. They gave a number of specific examples at a "C" level -- the sort of thing you'd never do without profiling, but might find useful if you've got a bottleneck. Sure enough, age-old solutions like manual loop unrolling were in there, and sure enough, even s
Re:I mostly disagree (Score:3, Informative)
Before flaming, it helps to actually check who, what and why invented Scheme.
Sussman and Steele's compiler was first of all an implementation of Hewitt's ACTORS, and second of all an interpreter that re-wrote Scheme in CPS style (along the way inventing general tail-recursion) targeted at Maclisp. The only "bloat" that Scheme fixed was the "funarg problem" of early lisps by introducing full
Re:Another marginal C++ feature (Score:1)
They're difficult to master for the library developer, for sure, but they provide unprecedented ease for the library user.
The idea has definitely caught on [microsoft.com] with other languages, too.
That's funny. (Score:2)
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.
Cute.. (Score:1)
Are there any good source for C++ in this kind of form
n00b question (Score:1)
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
Re:n00b question (Score:2)
I believe it's because "\x0012345678" represents a single character (with hexadecimal code 12345678) followed by '\0'. The number of digits in a character literal like that could be arbitrarily large.
In your other examples, "\x00f" is two characters, one with hexadecimal code f and the other '\0', while "\00g" is three characters, '\0', 'g' and '\0': the 'g', not being a hexadecimal digit, terminates the preceding character literal and stands in its own right.
Re:n00b question (Score:2)
For example, to create a string containg a null character followed by the digits 1 thru 9, you'd say: char z[] = "\000123456789" ; which gives you a 10-character string followed by the trailing null (i.e., (11 == sizeof z) is true).