tags:

views:

746

answers:

4

According to this article from Herb Sutter, one should always pick Class Specializing over Function Overload and definitely over Specialized Function Templates.

The reason is that

  • Specializations don't overload. Overload resolution only selects a base template (or a nontemplate function, if one is available). Only after it's been decided which base template is going to be selected, and that choice is locked in, will the compiler look around to see if there happens to be a suitable specialization of that template available, and if so that specialization will get used.
  • we can’t particial specialize function templates.

I must admit that before I read the article I have banged my head against the wall a few times. Why isn’t he picking my specialized function …
After reading the article I’ve never used Specialized Function Templates again.

Example:

template <class T> void foo( T t);

We should write foo like this so we can specialize it with class templates instead of function specializing.

template<class T> 
struct FooImpl;

template <class T> void foo( T t) {
    FooImpl<T>::foo(t);
}

Now we can specialze the template and don’t have to worry about the overload rules and we can even partitial specialize the template like this:

template<class U, class V> 
struct FooImpl< QMap< U, V > >;


Here is the question.

It seems that the StackOverflow members prefer Specialized Function Templates?
Why? Because the Specialized Function Templates get a lot more upvotes than the Overload Solutions and the Class Specializing.
With the information that i have at the moment i find it perverse because i know that i can get it right, but i know that the one who comes after me will hit the wall.

There are already some links to the GOTWCA article so you must have read the article. This means that upvoters must have some extra information, please stand up and enlighten me.

+2  A: 

You are assuming here that SO voters are all gurus - they are not. Many technically incorrect answers get upvoted.

As the author of the answer that I think you are referring to, well, as I said in my comment, it's not an issue I care (or know) all that much about, because I very rarely use template specialisation. I suppose could have deleted the answer, but it is technically correct and does seem to have sparked some useful debate on the topic.

And note that it is currently third in points (probably get downvoted after this) and that another answer that uses a completely different approach to the problem has been accepted.

anon
That is the most recent one ... the second one is template specializing. I just want to bring it in the open. Now that I've re-read the accepted one, the answer is kind of a class specialization ;-)
TimW
+2  A: 

As Neil pointed out, most correct answers will get voted up. And answers already at the top tend to get even more upvotes in my experience.

As to why: I guess specialized function templates are easier to understand, so that is what makes them preferable in example code.

Tobias
Have you read the article and still you say ... "specialized function templates are easier to understand". For me Overload Function is the easiest one to grasp.
TimW
I don't think he means that the overload resolution of specialised functions templates are easy to understand - he is saying the code is easier to read/more concise.
CiscoIPPhone
Yes, that's what I meant. Thank you.
Tobias
+2  A: 

First of all, I'm not an upvoter (of whatever you talk about).

The votes don't usually warrant correctness; there are even slightly incorrect answers that got accepted, plus the upvotes are often related to the time when a particular answer was posted, etc.

To your problem and the article: I have read the article, and I don't see any argument for what you suggest, that would not apply for plain function (template) overloading. The trick basically does exactly the same thing that would the compiler do, if you've used function template specializations (incl. partial, if they were allowed), with all the disadvantages Herb Sutter talks in the article. So, I don't think your way is "right" (in your words), I just think it is an ugly way to achieve something you don't need.

Compare:

Your partial specialization:

template<class U, class V> 
struct FooImpl< QMap< U, V > >;

Function overload:

template<class U, class V> 
void foo(QMap< U, V > ) { ... }

etc.

Even SFINAE is possible, function (template) partial ordering follows almost the same rules as template specialization resolution...

jpalecek
Well you have a point there, why not stick to overload functions. Why shouldn't we create a new base template and apply overload.
TimW
I usually prefer function template overload to that class template forwarding thingy. But partial order of function templates is difficult to do, and the Standard is quiet or at least very secret about some of the issues. It's easy to get two templates un-ordered, too. Whereas putting forward to a class template specialization is more straight forward. I think that's why Herb sutter proposes class template specializations.
Johannes Schaub - litb
+3  A: 

The problem with explicitly specialising a function temmplate only applies if the function is also overlaoded:

template <typename T> void foo (T*);   // #1

template <typename T> void foo (T);    // #2
template <> void foo<int*> (int*);

int main () {
  int * i;
  foo (i);  // Calls #1 not specialization of #2
}

Without the #1 overload, the code will work as expected. However, a function that starts out not being overloaded may have overloads added as the code is maintained into the future.

This is one of those examples where, although I hate to say it, C++ has too many ways to do the same thing. Personally, if you find you need to specialise a fucntion template, then I like the pattern suggested by TimW in his comment against Neil Butterworth's answer, ie. it's best to do so by having the current function dispatch it's call to a specialized class template instead:

template <typename T> class DoFoo {
    static void do (T) { /* default behaviour */ }
};
template <> class DoFoo<int*> {
    static void do (int*) { /* int * behaviour */ }
};

template <typename T> void foo (T t)
{
  DoFoo<T>::do (t);
}

If 'foo' is overloaded, then at least it's clearer to the developer that this function won't be called, ie. the developer doesn't need to be a standards guru to know how the specialization rules interact with overload resolution.

Ultimately, however, the code generated by the compiler is going to be the same, this is purely a code comprehension issue on the part of the developer.

Richard Corden
I think the Standard has it right: "When writing a specialization, be careful about its location; or to make it compile will be such a trial as to kindle its self-immolation." at 14.7.3/7 :)
Johannes Schaub - litb