Slashdot Mirror


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

89 comments

  1. Why is this here? by jbrandon · · Score: 3, Informative

    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.

    1. Re:Why is this here? by devphil · · Score: 4, Interesting
      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.

      --
      You cannot apply a technological solution to a sociological problem. (Edwards' Law)
    2. Re:Why is this here? by saden1 · · Score: 1, Insightful

      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.

      --

      -----
      One is born into aristocracy, but mediocrity can only be achieved through hard work.
    3. Re:Why is this here? by Gilk180 · · Score: 2, Interesting

      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.

    4. Re:Why is this here? by Anonymous Coward · · Score: 0

      Then I guess you don't know C++.

    5. Re:Why is this here? by dthable · · Score: 2, Insightful

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

    6. Re:Why is this here? by renehollan · · Score: 1
      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!

      --
      You could've hired me.
    7. Re:Why is this here? by jbrandon · · Score: 1

      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.

    8. Re:Why is this here? by Anonymous Coward · · Score: 0

      Come on, Stroustrup (the definitive language manual) first explained template specialization nearly ten years ago.

    9. Re:Why is this here? by saden1 · · Score: 1

      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.

      --

      -----
      One is born into aristocracy, but mediocrity can only be achieved through hard work.
    10. Re:Why is this here? by E_elven · · Score: 1

      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.

      --
      Marxist evolution is just N generations away!
    11. Re:Why is this here? by saden1 · · Score: 1

      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?

      --

      -----
      One is born into aristocracy, but mediocrity can only be achieved through hard work.
    12. Re:Why is this here? by orthogonal · · Score: 5, Informative

      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.

    13. Re:Why is this here? by Curien · · Score: 1

      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.

      --
      It's always a long day... 86400 doesn't fit into a short.
    14. Re:Why is this here? by 4of12 · · Score: 1

      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.

      --
      "Provided by the management for your protection."
    15. Re:Why is this here? by Anonymous Coward · · Score: 0

      And that's what I thought too, before I learned templates.

    16. Re:Why is this here? by Mr.+Slippery · · Score: 1
      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++ probably can't believe this, but I never worked on a project where we even used the STL (much less rolled our own templates) until about two years ago.

      --
      Tom Swiss | the infamous tms | my blog
      You cannot wash away blood with blood
  2. Parametric polymophism. by Daleks · · Score: 1, Insightful
    Why do
    template
    <typename A, typename B>
    A f(B b)
    {
    ...
    }
    when you can do
    let f b = ...
    1. Re:Parametric polymophism. by kruntiform · · Score: 2, Funny

      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.

    2. Re:Parametric polymophism. by Tom7 · · Score: 1

      Amen! Not to mention that you then have a first class object, rather than some bizarre "meta" object...

    3. Re:Parametric polymophism. by dthable · · Score: 1

      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?

    4. Re:Parametric polymophism. by renehollan · · Score: 2, Informative
      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.

      --
      You could've hired me.
    5. Re:Parametric polymophism. by Curien · · Score: 0

      While functions as first-class values are indeed useful, it is not necessary for any of those three tasks.

      --
      It's always a long day... 86400 doesn't fit into a short.
    6. Re:Parametric polymophism. by Tom7 · · Score: 1

      I don't mean object in the "object oriented" sense, sorry for the confusion.

    7. Re:Parametric polymophism. by Tom7 · · Score: 1

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

    8. Re:Parametric polymophism. by renehollan · · Score: 2, Insightful
      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.

      --
      You could've hired me.
    9. Re:Parametric polymophism. by scrytch · · Score: 0, Flamebait
      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 Loki library by the author of the aforementioned book. This library, recall, is supposed to make powerful constructs easier to work with...

      Incidentally, to the idiot moderator, the preceding example was ocaml, not BASIC.
      --
      I've finally had it: until slashdot gets article moderation, I am not coming back.
    10. Re:Parametric polymophism. by Old+Wolf · · Score: 1

      Why do
      (Score:2, Flamebait)

      when you can do
      (Score:5, Informative)

  3. Horrible example by 2megs · · 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 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.

    1. Re:Horrible example by renehollan · · Score: 3, Insightful
      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.

      --
      You could've hired me.
    2. Re:Horrible example by 2megs · · Score: 1
      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 string, and expect it to behave as something other than what it really is.

      I see the pointers in my example as pointers because they were declared to be pointers. If they'd been declared as std::string, I would see them as abstract strings whose implementation details are hidden. These are different things with unique properties, and it is very reasonable to expect that a generic "greater" function would compare ints as ints, pointers as pointers, and string objects as string objects.

      My complaint with this example is that it causes pointers to be silently treated as string objects rather than pointers. Unexpected behavior is bad when you've got a codebase into the millions of lines. In a team where someone else wasn't aware of this exception to the expected behavior of the "greater" function, this could easily turn into a very annoying bug to track down.

    3. Re:Horrible example by Curien · · Score: 1

      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.

      --
      It's always a long day... 86400 doesn't fit into a short.
    4. Re:Horrible example by Anonymous Coward · · Score: 0

      The behavior you expect from "greater" is virtually useless. Unless two pointers point into the same array, comparing or subtracting them gives unspecified behavior (only == and != are allowed).

    5. Re:Horrible example by renehollan · · Score: 2, Insightful
      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 (unsigned chars, const chars, const unsigned chars). The only grief with this approach is that you can't partially specialize non-member function templates and must resort to a class.

      --
      You could've hired me.
    6. Re:Horrible example by Old+Wolf · · Score: 1

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

    7. Re:Horrible example by Anonymous Coward · · Score: 0


      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.

      The pointer to a NUL-terminated sequence of chars is only sometimes a text string, you idiot. A char* variable may be pointing to a buffer of binary data, and I would be positively pissed if a > b did a lexicographical compare in this case.


      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 (unsigned chars, const chars, const unsigned chars). The only grief with this approach is that you can't partially specialize non-member function templates and must resort to a class.


      This is so fucking lame. Again, if you have a const char*, there is no way to tell from the type : const char* that you have a string of text, or just a pointer to some binary data.
      Finally, if you override the operators for char* pointers, how the fuck are you going to legitimately compare pointer values (and don't say use a cast, that would be completely gay considering that everything would have worked fine before you fucked it up with some marginally useful syntatic sugar).

      There is a reason for std::string, nimrod.

    8. Re:Horrible example by Anonymous Coward · · Score: 0

      And if the team member assumed there would be such a sensible exception (compare C-style strings as strings... what a concept!)

      Except C-style strings do not have enough decoration that the compiler knows they are strings of text and not binary data. char* may be a NUL terminated string, or it may be a packet buffer.

    9. Re:Horrible example by Anonymous Coward · · Score: 0

      The behavior you expect from "greater" is virtually useless. Unless two pointers point into the same array, comparing or subtracting them gives unspecified behavior (only == and != are allowed).


      Not really useless you idiot. If one is implementing a ring buffer or some container of bytes with multiple pointers pointing into various locations, the greater then and subtraction operators become very useful.

      Pointer arithmetic (including behavior of -, ) is well defined in the standard. Why don't you research the facts before making an idiot out of yourself?

    10. Re:Horrible example by renehollan · · Score: 1
      The pointer to a NUL-terminated sequence of chars is only sometimes a text string, you idiot. A char* variable may be pointing to a buffer of binary data, and I would be positively pissed if a > b did a lexicographical compare in this case.

      *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 you object). Perhaps you have never dealt with legacy code.

      In any case, an existing program which overloads char* to point to various kinds of pseudo-opaque data already has the problem you describe -- defining operator>(const char *, const char *) makes them no worse. Not defining it, or defining it to throw an exception could catch this, of course, but you'll likely find that this causes you far more pain than type-safety, when dealing with legacy code which is already fast and loose, typewise. If the genie ain't gonna get back into the bottle, might as well learn to live with it.

      That is not, of course, an argument to use this in new code.

      This is so fucking lame. Again, if you have a const char*, there is no way to tell from the type : const char* that you have a string of text.

      Guess what. There's no way to tell that a const Foo* points to a Foo, either, or that any pointer points to to ab object of the type claimed, or idiomatically implied. Casts are your enemy with regard to type-safety, and there are a million ways from Sunday to "fuck", as you would say, with the type-safety of a piece of code. <static_cast>, <dynamic_casr>, and <reinterpret_cast> help a bit, but RTTI makes code fat, and you aren't gonna make plain old casts go away.

      If you're going to live with C++, it is important to realize that type-safety really is a myth, with the compiler serving as a watchful servant, rather than a draconian master: if you want to shoot yourself in the foot, you can. C++ offers you a multitude of fully-automatic weapons for the purpose as opposed to C's handgun.

      Decades of history say that a char * is, much more likely than not, a pointer to a string (legacy C code written for compiler that didn't support void, excepted). Better to presume that it is, and try to remove the pesky exceptions when cleaning code up, than struggle against that inertia.

      --
      You could've hired me.
  4. Bad idea by Tom7 · · Score: 1


    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.

  5. Other ways to do it by WayneConrad · · Score: 1

    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.

  6. Hi fallutin' OO zealots!!! by Anonymous Coward · · Score: 0

    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.

    1. Re:Hi fallutin' OO zealots!!! by renehollan · · Score: 2, Informative
      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.

      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 queue of functors that do the "undo"ing. Try doing that with a function pointer.

      Also, because one has the opportunity to bind the function to it's parameters at different times, they don't all have to be known at the same time.

      I've put functors to good use when dispatching encapsulated function calls with queues of functions to call when those calls result in later callbacks in a multithreaded system -- there being a relationship in the dispatched functors and the callback parameters. You really should read Modern C++ Design to develop an appreciation for these techniques. They aren't obvious at first.

      --
      You could've hired me.
    2. Re:Hi fallutin' OO zealots!!! by E_elven · · Score: 1

      >A functor is far more than a "function pointer".

      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.

      --
      Marxist evolution is just N generations away!
    3. Re:Hi fallutin' OO zealots!!! by orthogonal · · Score: 1

      However, I disagree on the non-obviousness and generally oppose any techniques that are not obvious to developers.

      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 thought, "what a cool idea, what a good idea!"

      If your developers are not learning, they're doing you a disservice and them selves a disservice. Soon enough, techniques that are "advanced" now will become more common, and your developers won't be up to speed, either for you or for their next jobs.

    4. Re:Hi fallutin' OO zealots!!! by scrytch · · Score: 1

      Please to partially evaluate your function pointer then stuff it into a queue of callbacks that counts the number of times this callback has been queued, without actually scanning the queue, because it may be too large. In C.

      This is a real world example, incidentally.

      --
      I've finally had it: until slashdot gets article moderation, I am not coming back.
  7. Huh, where's the beef... by joto · · Score: 1

    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?

  8. Re:C++? by Anonymous Coward · · Score: 0

    You, sir, are an idiot.

  9. why is this newsworthy ? by sir_cello · · Score: 0, 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 ?

    1. Re:why is this newsworthy ? by wandazulu · · Score: 2, Informative

      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.

    2. Re:why is this newsworthy ? by sir_cello · · Score: 1


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

  10. It just gets even more convoluted by Viol8 · · Score: 3, Insightful

    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.

    1. Re:It just gets even more convoluted by Curien · · Score: 1

      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.

      --
      It's always a long day... 86400 doesn't fit into a short.
    2. Re:It just gets even more convoluted by Viol8 · · Score: 2, Insightful

      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 and no less obfuscated"

      That may be true , but using your example its a damn site easier to grep through some source code for "add(" and get maeningfull output than for
      the + operator!

    3. Re:It just gets even more convoluted by renehollan · · Score: 2, Insightful
      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 objects of those types. That is not an argument against user-defined objects or operator overloading, but one for proper architecture with no extraneous types or templates.

      Basically, these mechanisms make it easier to use the implementation language to express code architecture and design pattern models -- programming at a higer level of abstraction if you will, but programming nevertheless. The trouble is that many so-called "programmers" lack the skill to do this and get miffed.

      --
      You could've hired me.
    4. Re:It just gets even more convoluted by Viol8 · · Score: 1

      "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 few could program the same in assembler , and if they can't even understand what a stack or a queue is then
      they don't have a prayer of being able to code them low level.

    5. Re:It just gets even more convoluted by elflord · · Score: 1
      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 wanted to. Disallowing operator overloading because someone might abuse it is like requiring all function names to contain 10 or more characters, because someone might choose an incomprehensible name.

    6. Re:It just gets even more convoluted by Old+Wolf · · Score: 1

      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.

    7. Re:It just gets even more convoluted by Viol8 · · Score: 1

      That will show you where its defined , not where its used.

      "open your IDE and click go-to-definition,"

      Err , my IDE here is vi and grep. The debugger is dbx. Need I say more?

    8. Re:It just gets even more convoluted by Mr.+Slippery · · Score: 2, Insightful
      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.

      --
      Tom Swiss | the infamous tms | my blog
      You cannot wash away blood with blood
    9. Re:It just gets even more convoluted by Anonymous Coward · · Score: 0

      Err , my IDE here is vi and grep. The debugger is dbx. Need I say more?

      Use better tools.

  11. Upcoming "Developers" Headlines: by avdi · · Score: 2, Funny

    Variable Assigment in Java
    Using Perl Regular Expressions to Process text
    Python Operator Overloading
    Using Lisp Macros

    --

    --
    CPAN rules. - Guido van Rossum
    1. Re:Upcoming "Developers" Headlines: by Haeleth · · Score: 1

      You forgot "Advanced BASIC: The GOTO Statement"...

  12. Is this even correct C++? by snjoseph · · Score: 1
    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?
    1. Re:Is this even correct C++? by renehollan · · Score: 1

      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.

      --
      You could've hired me.
    2. Re:Is this even correct C++? by drxenos · · Score: 1

      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.

      --


      Anonymous Cowards suck.
    3. Re:Is this even correct C++? by renehollan · · Score: 1
      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 be equivalent.

      --
      You could've hired me.
    4. Re:Is this even correct C++? by drxenos · · Score: 1

      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 none in the examples. Partial specialization does not mean part of full specialization. They are two different animals.

      --


      Anonymous Cowards suck.
    5. Re:Is this even correct C++? by renehollan · · Score: 2, Insightful
      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 X<int, long> { ... };

      or template <> class X<int, long> { ... };

      though, technically the last example above is an explicit specialization, whereas the one above it is a full specialization.

      You're talking about cases like

      template <typename T> class X<T, T&> { ... }

      which are also partial template specializations.

      But, I reiterate, you can't partially specialize member functions or non-member functions in the same way -- you can only totally specialize member functions and use overloading for non-member functions to similar effect. I recall that the syntax for non-member functions allows a fully-specialized template syntax to be used (instead of simple signature overloading), but I may be mistaken there.

      So,

      template <typename T, typename U> void f(T t, U u) { ... }

      void f(int t, long u)<int, long> { ... }

      as opposed to simply

      void f (int t, long u) { ... }

      The first would be a full specialization and the latter a simple overload. Something in my mind tells me that the full specialization function syntax is, in fact, legal, though I don't have the time to try it now.

      See Alaxandrescu, Andrei, "Modern C++ Design", Addison-Wesley, New York, 2001, pp. 26-28.

      --
      You could've hired me.
    6. Re:Is this even correct C++? by drxenos · · Score: 1

      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 function. Scott Meyers had a really great article on why this is true in (I believe) "The C/C++ Users Journel" several months back. I, too, thought function templates were specialized until I read it. Hopely, its available somewhere online. He even showed how just changing the order between overloaded versions would change with one the compiler would use. DrX

      --


      Anonymous Cowards suck.
    7. Re:Is this even correct C++? by drxenos · · Score: 1

      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

      --


      Anonymous Cowards suck.
    8. Re:Is this even correct C++? by renehollan · · Score: 1
      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 specialization or (2) in dealing with overloaded functions, the compiler chooses the more "specialized" form.

      Ah! This explains my failure to understand you at first (and, less charitably, think you completely wrong -- good thing I assumed we had a semantic disconnect, and discarded that unflattering opinion).

      I still haven't verified whether full template specialization of non-member functions is supported. It (as would partial template specialization) be useful: what if you wanted to have multple alternate function implementations that did not vary as a function of parameter types (which overloading provides)? Sometimes, you really do want the compiler to pick the correct kind of Foo(), regardless of whether it is overloaded, formal-parameter wise. To wit: the instantiation of an overloaded (or not) non-member function depends on several types, only some of which may matter at run-time (those of it's parameters). In particular, the lack of partial template non-member function specialization prevents selection of different function implementations with identical parameter signatures to coexist at run time, or even be uniquely selected at compile time.

      Of course, member template functions suffer no such restrictions. I suppose a workaround to simulate non-member partially specialized functions would be to encapsulate the function in a template class, and partially specialize that, as required. In fact, if the class provided a static () operator (Hmm. Are static member operators supported?), this would dovetail nicely:

      template <typename T, typename U> class Foo { public: static T &operator(){int i, U& u} { ... } };

      template <typename T> class Foo<T, unsigned long> { public: static T &operator(){int i} { ... } };

      So, we could have ::Foo<T, U>(7, u) == ::Foo<T>(7)

      Dunno if that's legal. Time to ask my compiler and, if the result if fruitful, check the standard to see if it's portable.

      --
      You could've hired me.
    9. Re:Is this even correct C++? by Anonymous Coward · · Score: 0

      You can do both, but they're different. E.g. if MyClass declared f as a friend, MyClass would befriend the template specialization (example 1), but not the overload (example 2).

      You can't do partial specialization on function templates (yet), though.

  13. Another marginal C++ feature by Animats · · Score: 3, Insightful
    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. 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.

    1. Re:Another marginal C++ feature by tamboril · · Score: 1
      If you think C++ templates are marginally useful, check out what you can do 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 with other languages, too.

  14. That's funny. by blair1q · · Score: 1

    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.

  15. Cute.. by shadowpuppy · · Score: 1

    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.

  16. I mostly disagree by devphil · · Score: 2, Interesting
    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. 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.

    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.

    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.

    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.

    (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)
    1. Re:I mostly disagree by Animats · · Score: 1
      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 lack of debuggability. At least with macro processors, you can look at the output. Combined with a language like C++, which has hiding without safety, it can only lead to trouble.

      As for the examples, they show loop unwinding on an RS6000. The generated code is more appropriate for an earlier model PowerPC. The RS6000 has register renaming, so it's not necessary to use a different register for each successive operation to get instruction level parallelism.

      Register renaming is what made loop unrolling obsolete. In the x86 world, register renaming came in with the Pentium Pro. For x86, it's essential if you want to get much instruction level paralleism, since there are so few registers. Once that worked, it was possible to get several iterations of the same loop going at the same time.

      The downside of loop unrolling is code bloat, which leads to cache misses.

      Up at the source level at which Blitz is working, the unrolling template has no idea of what's going on down at the machine level. Doing a machine-level optimization at the source level can well be a lose.

      I used to do some heavy number-crunching involving a code generator that unwound big mechanical engineering problems into huge blocks of straight-line C code. In 1990, this was a clear win. By 1998, it was a clear lose.

    2. Re:I mostly disagree by Anonymous+Brave+Guy · · Score: 1

      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 state of the art compilers on PCs still miss a lot of even the more basic "hand coded" optimisations.

      Certainly trying to do it yourself can be a lose, particularly with a solid compiler on a recent processor with clever pipelining tricks. However, there is still a reason that libraries like Blitz are well regarded, and that reason is that, for now, their output code is still much faster than most people's "normal" code.

      --
      If you disagree, post your argument. (-1, Overrated) isn't your personal censorship tool for views you don't like.
    3. Re:I mostly disagree by voodoo1man · · Score: 2, Informative
      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 lexical scoping (along the way inventing the closure) and applicative order reduction/evaluation for function arguments, a convention that most later Lisps adopted (those that did not reportedly disappeared without a trace in the 1980s). The original Scheme did not include macros, and didn't have FEXPRS (ie - all functions evaluated their arguments, as mentioned above), but it did have quote, which is enough to build macros. I'm pretty sure they used some form of macros for transforming special forms to lambdas (off the top of my head, I think Steele mentions dirty macros in Compiler Optimization based on viewing LAMBDA as rename plus GOTO in Winston, ed, Artificial Intelligence - An MIT Perspective, Vol. 2). I know AI Memo 349 (Sussman, Steele, SCHEME an interpteter for extended lambda calculus) mentions something about AMACROs in the implementation.

      But certainly neither of them disparaged macros (as a matter of fact, I do recall a not too old discussion on the Lighweight Languages mailing list where Steele defends macros against an attack using the same (lack of) arguments as yours).

      PS - yes, it certainly was too late for Scheme, but luckily they added syntax-case back in somewhere around R4RS. Better late than never.

      --

      In the great CONS chain of life, you can either be the CAR or be in the CDR.

  17. n00b question by Old+Wolf · · Score: 1

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

    1. Re:n00b question by Anonymous Coward · · Score: 0
      The escape \ooo consists of the backslash followed by one, two, or three octal digits that are taken to specify the value of the desired character. The escape \xhhh consists of the backslash followed by x followed by one or more hexadecimal digits that are taken to specify the value of the desired character. There is no limit to the number of digits in a hexadecimal sequence. A sequence of octal or hexadecimal digits is terminated by the first character that is not an octal digit or a hexadecimal digit, respectively. The value of a character literal is implementation-defined if it falls outside of the implementation-defined range defined for char (for ordinary literals) or wchar_t (for wide literals).

      I believe this is because CHAR_MAX is implementation-defined, and may be much greater than 127 or 255.

    2. Re:n00b question by Anonymous+Brave+Guy · · Score: 1

      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.

      --
      If you disagree, post your argument. (-1, Overrated) isn't your personal censorship tool for views you don't like.
    3. Re:n00b question by shakah · · Score: 1
      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).

  18. But obvious (or not) to whom? by Anonymous+Brave+Guy · · Score: 2, Insightful
    You really should read Modern C++ Design to develop an appreciation for these techniques. They aren't obvious at first.

    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.