6

I'm reading

Primer C++ > Adventures in Functions > Templates > Explicit Specialization.

To show the reason/use for Explicit Specialization, a case is illustrated:

Consider a swap template function that can swap any type (int, double, struct etc...)

But there is a specific struct job that you want to only swap two members of, and leave the rest of the members as they are. You will need a different definition, and so you will have to make an Explicit Specialization.

There is this statement in the same section:-

"A specialization overrides the regular template, and a non-template function overrides both."

Why not just make a regular function for that use? Then a regular/non-template will override the template, isn't it?

If my solution is correct, then what is a good example for Explicit Specialization?

iammilind
  • 68,093
  • 33
  • 169
  • 336
wajed
  • 503
  • 2
  • 6
  • 10

4 Answers4

10

One of the use case for explicit specialization is to avoid regular function to be skipped when some changes happens in the actual template function. To understand see below example:

template<typename T1, typename T2>
void foo(T1 o1, T2 o2)  // template function
{}
void foo(int o1, int o2) // regular function overloaded
{}

Till now it's fine. Now after sometime you got to change the definition of template<> foo()

template<typename T1, typename T2, typename T3> // new parameter added
void foo(T1 o1, T2 o2, T3 o3)  // template function
{}

You changed all the calls to foo() accordingly, but you missed/messed to change the regular overloaded function foo(). Then, it's a disaster ! Because compilation would go fine and regular calls would be silently replaced by the template<> foo(), which is undesired.

Now, had there been an explicit specialization such as,

template<>
void foo(int o1, int o2) // explicit specialization
{}

then that function will give you compilation error due to unmatched parameters and which would remind you of corresponding changes.

The other usage or (difference) is that an explicitly specialized function can be included in header file without any concern of multiple symbol linking error. Note that, explicit specialization has its own drabacks also, but I have demo a good side of it.

iammilind
  • 68,093
  • 33
  • 169
  • 336
  • `template<> void foo(int o1, int o2) {...}` is not the correct syntax to specialize `template void foo(T1 o1, T2 o2) {...}`. The correct syntax is `template<> void foo(int o1, int o2) {...}` – Serge Dundich Jun 20 '11 at 06:30
  • @Serge, first syntax is equally correct and it compiles fine with gcc also. The 2nd syntax you suggested is also correct but mentioning `` for functions is redundant when you already mention arguments as parameters. That syntax is useful for `class` specialization though. – iammilind Jun 20 '11 at 06:34
  • @iammilind: I'm not saying that code is incorrect or won't compile. I'm saying that it is not the correct syntax for specialization of `template void foo(T1 o1, T2 o2) {...}`. In fact `template<> void foo(int o1, int o2) {...}` is different function template overload (with zero template parameters). – Serge Dundich Jun 20 '11 at 08:52
  • @Serge Dundich, If that is the case it's worth starting a new question for difference between the 2 version. May be we will get more inputs. on the same. Because if both versions are different then both can overload each other. Which doesn't happen http://www.ideone.com/TQYU9 – iammilind Jun 20 '11 at 10:14
  • @iammilind: "if both versions are different then both can overload each other. Which doesn't happen" They indeed may both be candidates for overloading and the most specialized function template overload wins (as usual). – Serge Dundich Jun 20 '11 at 10:19
  • @iammilind: Actually `template<> void foo(int o1, int o2) {...}` is almost similar to function overload version. The differences are: (1) function overload (if existed) would override it, (2) you may call it like `{ int x,y; foo<>( x, y ); }` to specify that you are calling function template. – Serge Dundich Jun 20 '11 at 11:44
  • @iammilind: "can be included in header file without any concern of multiple symbol linking error" Also there is `inline` keyword for that purpose. – Serge Dundich Jun 20 '11 at 11:46
  • @Serge, I think you have completely misunderstood the answer. :) Anyways, let's not argue it further. – iammilind Jun 20 '11 at 11:51
  • @iammilind: What was that about accidentally calling `template void foo(T1 o1, T2 o2) {...}`? Here template parameter `int N` is undeducable and thus you must specify all tree parameters to call this function. Like this: `{ int x; double y; foo(x,y); }`. You cannot forget something and call it by accident instead of some overloaded function. – Serge Dundich Jun 20 '11 at 11:54
  • @iammilind: "I think you have completely misunderstood the answer." Really? What makes you think so? – Serge Dundich Jun 20 '11 at 11:55
  • @iammilind: You were right about `template<> void foo(int o1, int o2) {...}` syntax. It indeed may be used to define explicit `foo` specialization of `template void foo(T1 o1, T2 o2) {...}` if declared after general template declaration (because trailing template arguments may be deduced from argument list). I was not aware of that feature. I thought template parameter deduction is what happens only when you use function template. – Serge Dundich Jun 20 '11 at 12:29
  • @Serge, now you got the point. But due to our discussion, some one down voted my answer getting mislead by it. – iammilind Jun 20 '11 at 12:48
  • @iammilind: "now you got the point" I never missed the point. Syntax of explicit template specialization is not the point. Specialization vs overload difference is the point. I generally agree with the idea of your answer (though it is minor issue) but you still don't have good example code. Your code is confusing. What exactly user may forget and what undesirable effect he/she will get? If you fix your example code I'll +1 your answer. – Serge Dundich Jun 20 '11 at 16:45
0

Why not just make a (regular) function for that use? Then a regular/non-template will override the template?

Of course you can use regular function overload instead of explicit function template specialization if it is OK for you. But regular function overload will not be used if you explicitly use function template (by specifying template parameters).

Example:

You have function template:

template< class T >
void foo( T& x, const T& y )
{
...
}

Then if you specify function overload:

void foo( double& x, const double& y )
{
....
}

In the code like this:

template< class T >
void some_function( T& x )
{
    T y;
    ......
    foo<T>( x, y );
}

function overload void foo( double& x, const double& y ) will never be used.

But if you specify function template specialization

template<>
void foo<double>( double& x, const double& y )
{
....
}

Then some_function would use your specialization if you call

double x;

some_function(x);

somewhere.

Serge Dundich
  • 4,221
  • 2
  • 21
  • 16
0

Standard functions may be specialized but may not be overloaded, just for one example. Another example would be where the types are non-deducible and you have existing code which calls them with explicit template arguments- your overload is worthless then.

Puppy
  • 144,682
  • 38
  • 256
  • 465
0

Another usage is to mark a special case of templated function as not callable.

template<typename T>
void processPointer(T* ptr);
template<>
void processPointer<void>(void*) = delete;
template<>
void processPointer<char>(char*) = delete;

(From Effective Modern C++)

Zack Light
  • 167
  • 2
  • 11