|
||||
|
Section 35:
|
[35.7] My template function does something special when the template type T is int or std::string; how do I write my template so it uses the special code when T is one of those specific types?
Before showing how to do this, let's make sure you're not shooting yourself in the foot. Does the function's behavior appear different to your users? In other words, is the observable behavior different in some substantive way? If so, you're probably shooting yourself in the foot and you will probably confuse your users — you're probably better off using different functions with different names — don't use templates, don't use overloading. For example, if the code for int inserts something into a container and sorts the result, but the code for std::string removes something from a container and does not sort the result, those two functions ought not to be an overloaded pair — their observable behavior is different so they ought to have different names. However if the function's observable behavior is consistent for all the T types with the differences limited to implementation details, then you can proceed. Let's proceed with an example of this (conceptual only; not C++):
template<typename T>
void foo(T const& x)
{
switch (typeof(T)) { ← conceptual only; not C++
case int:
... ← implementation details when T is int
break;
case std::string:
... ← implementation details when T is std::string
break;
default:
... ← implementation details when T is neither int nor std::string
break;
}
}
One way to implement the above is via template specialization. Instead of a
switch-statement, you end up breaking up the code into separate
functions. The first function is the default case — the code to be
used when T is anything other than int or std::string:
template<typename T>
void foo(T const& x)
{
... ← implementation details when T is neither int nor std::string
}
Next are the two specializations, first for the int case...
template<>
void foo<int>(int const& x)
{
... ← implementation details when T is int
}
...and next for the std::string case...
template<>
void foo<std::string>(std::string const& x)
{
... ← implementation details when T is std::string
}
That's it; you're done. The compiler will automagically select the correct
specialization when it sees which T you are using.
|
|||