Catch up on stories from the past week (and beyond) at the Slashdot story archive

 



Forgot your password?
typodupeerror
×
Programming Software IT Technology

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.""
This discussion has been archived. No new comments can be posted.

Function Template Specialization in C++

Comments Filter:
  • Why is this here? (Score:3, Informative)

    by jbrandon ( 603700 ) on Tuesday November 11, 2003 @09:37PM (#7450311)
    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.
    • Re:Why is this here? (Score:5, Interesting)

      by devphil ( 51341 ) on Tuesday November 11, 2003 @09:51PM (#7450373) Homepage
      It's a very basic introduction to a very deep subject. Anyone who knows C++ knows the vast majority of this information.

      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.

      • Frankly, if you want to see what templates and partial specialization can really do, go get Andrei Alexandrescu's book "Modern C++ Design".

        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)

        by orthogonal ( 588627 ) on Wednesday November 12, 2003 @03:07AM (#7451611) Journal
        get Andrei Alexandrescu's book Modern C++ Design

        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.
    • by saden1 ( 581102 )
      Anyone who knows C++ knows the vast majority of this information.

      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.
      • by dthable ( 163749 )
        A lot of people are in this boat of thinking of C++ as C with classes. Unless you really got into the last standard or had a need to use templates, STL, namespaces, etc. there was never a need to learn them.

        But hey, would you expect any less from /.?
      • I found this artical very informative and definitely worth the read.

        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 /. material, just like tutorials in other languages are not /. material.
        • You are assuming that just because I found the article informative that I know a little bit of C++.

          C++ is not synonymous with STL templates...It is a feature the use of which is not mandatory.

          • Templates have nothing to do with the STL -which in turn has everything to do with templates. The article, however, did not touch the STL.

            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.

            • It is late for me here but that should have read STL and Templates.

              "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?

            • 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.

            • In any case, if you don't know how templates work, you only know a little bit about C++.

              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

          • Templates is such a large part of the language that I /would/ say you know little about C++ if you don't know templates. It's like saying you know C except for pointers.
    • Re:Why is this here? (Score:2, Interesting)

      by Gilk180 ( 513755 )
      It may be a very basic introduction, but the statement that "anyone" knows this information is probably not true.

      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.
  • Why do
    template
    <typename A, typename B>
    A f(B b)
    {
    ...
    }
    when you can do
    let f b = ...
    • If I may troll just a little, the first one is better because most programmers are afraid of anything that doesn't look like C and because they like to type in lots of boilerplate code because it makes them feel productive.
    • Amen! Not to mention that you then have a first class object, rather than some bizarre "meta" object...
      • The first item is defining a function. Why should I care if the language makes it an object or a function as long as it does what I want when I call it?
        • Why should I care if the language makes it an object or a function as long as it does what I want when I call it?

          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.

          • While functions as first-class values are indeed useful, it is not necessary for any of those three tasks.
            • Fuck, man, nothing is "necessary" for a progamming task. I can code up any feature in C, just as I can code up any feature in ML. But partial application and closures are a extremely painful in C++. (Yes, I have seen the Boost library.)
              • But partial application and closures are a extremely painful in C++.

                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.

        • I don't mean object in the "object oriented" sense, sorry for the confusion.
    • Some nitwit moderator called the last post a troll. So mod this repost too:

      Why do

      template
      &lt;typename A, typename B&gt;
      A f(B b)
      {
      ...
      }

      when you can do

      let f b = ...

      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

    • Why do
      (Score:2, Flamebait)

      when you can do
      (Score:5, Informative)

  • 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
    • by renehollan ( 138013 ) <<ten.eriwraelc> <ta> <nallohr>> on Tuesday November 11, 2003 @10:51PM (#7450694) Homepage Journal
      This is a perfect example of how NOT to use the expressive power of C++.

      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.

      • 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.

        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

        • And if the team member assumed there would be such a sensible exception (compare C-style strings as strings... what a concept!) and there wasn't, you'd have the same problem. If the standard library and just about every other library in existence weren't already littered with this kind of exception, you'd have a much stronger argument. As it is, you just sound beligerent.
          • Indeed. The pointer to NUL-terminated sequence of characters is sooo idiomatically a string from the "C days", that it's probably more understandable to preserve that idiom than not. Heck, that's the only way to implement string literals without the use of an object, and we know how much we love our string literals.

            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

    • He uses that "char const *" syntax too. Does anyone else use it?

  • 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
  • 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.
  • 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?

  • 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 ?
    • Unless you've done the majority of your C++ programming using VC4.1/4.2/5/6 which doesn't support this feature, but all of a sudden 7.1 does and you want to see what you've been missing.

      • 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 ...
  • by Viol8 ( 599362 ) on Wednesday November 12, 2003 @06:00AM (#7452001) Homepage
    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.
    • Oh, and that's so much better than

      A var1;
      B var2;
      add(var1, var2, &var3);

      Because now you know /exactly/ what's going on without bothering to read the function definition. Riiight.

      Seriously, operator overloading is just syntactic sugar for a function call: it's no more and no less obfuscated.
      • Actually I was thinking more:

        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
        • 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.

          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

        • I think it's easier to grep for "operator+" (or "operator[ \t]*\+" or whatever) than "add".

          Or you could whip open your IDE and click go-to-definition, or run the debugger and go step-into.
      • Seriously, operator overloading is just syntactic sugar for a function call: it's no more and no less obfuscated.

        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.

    • 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

      ...unless you understand the types A and B, and the meaning of operator+(const A&, const B&). If A and B represented arbitrary precision numbers, it would be perfectly natural to use operator+ for their addition.

      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

      • "if you don't understand the types in a program"

        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
  • by avdi ( 66548 ) on Wednesday November 12, 2003 @09:28AM (#7452815) Homepage
    Variable Assigment in Java
    Using Perl Regular Expressions to Process text
    Python Operator Overloading
    Using Lisp Macros
  • I don't have a compiler handy, but is the article even correct? As I understand it, you don't specialize function templates--you use the overload mechanism to achieve the desired result. That is, you wouldn't write:
    template <class T> void f(T);
    template <> void f<int>(int);
    but rather:
    template <class T> void f(T);
    void f(int);
    Am I wrong?
    • At first glance, both are correct: the former is a partial specialization that just happens to be full, and the latter is classic full template specialization syntax. The latter was a part of the language first.
      • Not true. There is no partial specialization in the two examples. The poster is correct: there is no full function specialization in C++. There is partial specialization, dealing with pointer and reference types, and there is overloading. Functions are not fully specialized. That is for classes only.

        • Eh? The second line is a partial specialization syntax of the function template, that just happens to not leave any type parameters left -- that is, it is fully specialized, and equivalent to the last line.

          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

          • You completely misintepreted what I said. I did not say there is no partial specialization for functions; there is. What I said is there is no full specialization for functions, and there's isn't. There is overloading and what is called "explicit specification." See "The C++ Programming Language", by Stroustrup, 3rd Edition section 13.3. Again, there is no partial specialization what so ever in his examples. Partial specialization involves pointers and references to unknown types. Of which there is n
            • Again, there is no partial specialization what so ever in his examples. Partial specialization involves pointers and references to unknown types. Of which there is none in the examples. Partial specialization does not mean part of full specialization.

              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

              • Your are correct about the first form of partial specialization. I wasn't thinking about this form because, as you said, it doesn't apply to functions. You have to be careful with functions with the term specialization. The word is overloaded (no pun intended). It can mean (1) template specialization or (2) in dealing with overloaded functions, the compiler chooses the more "specialized" form. Other than partial specialization (as in with pointers), there is really no template specialization with funct
                • Your are correct about the first form of partial specialization. I wasn't thinking about this form because, as you said, it doesn't apply to functions.

                  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

              • Ok, I found the article. I was fairly "back-asswards" in my remembrance of it (I even got the author wrong). It was actually Herb Sutter, and he argues that there *is* specialization, but not partial (which, I think, is what you stated). Interesting read, though. http://www.gotw.ca/publications/mill17.htm
  • by Animats ( 122034 ) on Wednesday November 12, 2003 @12:14PM (#7454242) Homepage
    There's a group of C++ programmers who are into abusing the template mechanism into a compile-time programming environment. This is not a good thing.

    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)

      by devphil ( 51341 )

      There's a group of C++ programmers who are into abusing the template mechanism into a compile-time programming environment. This is not a good thing.

      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.

      • There was once a fad for making C look like Pascal using defines. Didn't help.

        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

        • 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

        • In LISP, macros became so bloated that Scheme had to be invented to strip the language down. But it was too late.

          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

    • If you think C++ templates are marginally useful, check out what you can do [boost.org] with them.

      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.

  • 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 form
  • (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
    • 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.

    • To avoid this sometimes hard-to-notice bug, a lot of people embed such things in strings using octal escapes, which take a max of three (octal) digits -- if you always use 3 digits for these, you never get screwed.

      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).

A physicist is an atom's way of knowing about atoms. -- George Wald

Working...