Reputation: 1756
I'm trying to understand how template specialziations work. I've got the following function template:
template <typename T>
void function(const T &t1, const T &t2)
{
std::cout << "in function template: " << t1 << ", " << t2 << std::endl;
}
now, I want to specialize this function template in case it's called with a pointer to const:
// template specialization
template <>
void function(const char *&t1, const char *&t2)
{
std::cout << "in compare template specialization: " << t1 << ", " << t2 << std::endl;
}
but the compiler complains that it can't find a function template to specialize:
In file included from main.cpp:1:0:
template.h:23:5: error: template-id 'compare<>' for 'int compare(const char*&, const char*&)' does not match any template declaration
int compare(const char *&t1, const char *&t2)
^~~~~~~
template.h:10:5: note: candidate is: template<class T> int compare(const T&, const T&)
int compare(const T &t1, const T &t2)
if I specialize the template like this (a reference to a CONST pointer to const), it works:
// template specialization
template <>
int compare(const char * const &t1, const char * const &t2) // now the pointer itself is const
{
std::cout << "in compare template specialization: " << t1 << ", " << t2 << std::endl;
}
I want to call the function with a const char *Ptr = "hello world"
so I thought the inferred parameter T was char* and the parameter was const char *&.
Aren't the const in the function template parameter list always low level const?
Upvotes: 3
Views: 850
Reputation: 15943
Templates are not a simple token replacement mechanism like macros. const T
here doesn't mean "paste me whatever T
is into the spot right after the const
". It means that the type of the thing there is "const
whatever T
is". In the case of your function template, if you set T
to be const char*
then the type const T&
will be a reference to a const
whatever T
is, i.e., a reference to a const char*
that is itself const
, i.e., a const char * const &
. It's really no different than if T
was a typedef'ed name rather than a template parameter, e.g.:
using T = int*;
const T blub = 42; // type of blub is int* const, not const int*
Therefore,
template <>
void function(const char*& t1, const char*& t2);
is not a valid specialization of the function template function
. There is no T
that you could substitute into your template function
to get this signature. If you substitute const char*
for parameter T
, i.e., form function<const char*>
, its signature will come out to be
void function<const char*>(const char * const& t1, const char * const& t2);
Note that, rather than rely on explicit specialization, if you want a separate function to treat the
void function(const char*& t1, const char*& t2);
case, simply add such a function and rely on overloading to work its magic. In general, when you find yourself writing explicit function template specializations, odds are that what you actually wanted to do is probably just use overloading. See also Template Specialization VS Function Overloading or this article (old, but still as true as ever) for more on that…
Upvotes: 7