total template specialization
I'm reading the book of Meyers about effective c++ programming, in item 25 I found total template specialization
, b开发者_Python百科ut I can't understand it, what does that it mean? he also gives example:
namespace std {
template<>
void swap<Widget>(Widget& a, Widget& b)
{
swap(a.pimpl, b.pimpl);
}
}
what does this statement mean : template<>
(why without typename?)
thanks in advance
Typically you use templates because you have a piece of code that is generic enough that it can be applied to different types. However, for some types you may want to do something different (e.g. because there's a more efficient way of doing it). This is when template specialization comes to the rescue (you can think of them as "special case" templates):
For example:
class Foo {};
class Bar {};
// Primary template - the most generic.
template<typename T, typename U>
class MyClass
{
public:
void DoSomething()
{
/* Performs the same generic operation for all T and U... */
}
};
// Total specialization of the primary template
template<>
class MyClass<Foo, Bar>
{
public:
void DoSomething()
{
/* ...Except when T is Foo and U is Bar.
We may possibly do something different
to allow for higher efficiency. */
}
};
int main()
{
MyClass<int, char> a; // Uses the generic version of MyClass
MyClass<Foo, Bar> b; // Uses the (total) template specialization
}
Note that I'm using classes here, but the concept is the same. You can see that a similar syntax applies for function templates.
For classes, though, there is such a thing as partial template specialization, when not all the parameters are completely specified in the template specialization. It might look like this:
// Partial specialization #1
template<typename U>
class MyClass<Foo, U>
{
public:
void DoSomething()
{
/* ...Do something special when T is Foo.
This code doesn't care what type U is. */
}
};
template<typename T> class Baz {};
// Partial specialization #2
template<typename Z>
class MyClass<Foo, Baz<Z> >
{
public:
void DoSomething()
{
/* ...Do something special when T is Foo, and U is Baz.
This code doesn't care what Baz gets for its
template parameter. */
}
};
int main()
{
MyClass<int, char> a; // Uses the generic version of MyClass
MyClass<Foo, char> b; // Uses partial template specialization #1
MyClass<Foo, Baz<int> > c; // Uses partial template specialization #2
MyClass<Foo, Bar> d; // Uses the total template specialization
}
Note that there's no ambiguity when dealing with these specializations because the compiler picks the one that is the best fit for the template parameters. By allowing for these "special case" templates, we can create truly generic libraries.
Also note that this partial specialization business only works for classes, not functions! (You can't partially specialize function templates). That's why your code snippet is written the way it is - you can only totally specialize function templates - anything else is function overloading in the std
namespace (which the C++ standard disallows). I took the time to mention this because lots of people seem to get this wrong.
namespace std
{
/* Do **not** do this in the std namespace!!!
You're not actually partially specializing the function,
you're overloading the function in the std namespace
which is prohibited by the C++ standard. */
template<typename T>
void swap<Widget<T> >(Widget<T>& a, Widget<T>& b) {}
}
It's defining an implementation of the function swap<T>
for the case when T
is Widget
. It's "total" specialization because it specifies types for all the template parameters of swap<T>
(in this example there's just one).
You do this when your implementation of swap<Widget>
needs to do something different from the generic swap<T>
code.
The template<>
piece tells the compiler that you're providing a specialisation of a template. There's nothing between the <>
because there are no template parameters left to specify - the swap<Widget>
piece defines all the parameters.
精彩评论