Suppose I have a template that works with raw pointers:
template
void processPointer(T* ptr);
I don\'t want this to be called
This might give insight:
#include <iostream>
struct X
{
template<typename T>
void processPointer(T* ptr) {
std::cout << "Template\n";
}
// error: explicit specialization in non-namespace scope ‘struct X’
// template<>
// void processPointer(void*) = delete;
// Overload but no specialization
// This will prevent lookup the specialization outside the class, when no
// template argument is explicitly given. However, with an explicit
// template argument the specialization is called.
void processPointer(void*) = delete;
};
// Specialization outside the class body
template<>
void X::processPointer(void* ptr) {
std::cout << "Specialization\n";
}
int main ()
{
X x;
//error: use of deleted function ‘void X::processPointer(void*)’
//x.processPointer((void*)0);
// Explicit template argument:
x.processPointer<void>((void*)0);
}
Conclusion: The answer of @Casey holds.
Here's one reason to favor the template version: processPointer<void>(void*)
can still be invoked directly, avoiding the other overload.
Suppose you want to pass the argument pointer
of type void*
(or simply nullptr
) to your processPointer
function and you also want to call its specialization for type Type
. Then you should write
processPointer(static_cast<Type>(pointer));
for
void processPointer(void*) = delete;
But for
template<>
void processPointer<void>(void*) = delete;
you could write the code which is much shorter:
processPointer<Type>(pointer);
So both variants can be used in the different cases.
However the analogue of the variant with non-template overload can be the only way in some cases. Suppose there is a function template with two parameters:
template<typename T, typename U>
void processPointer(T* ptr1, U* ptr2);
You don't want it to be called with void*
pointers as the first argument. The partial specialization of function templates is not allowed in C++ so this code is incorrect:
template<typename U>
void processPointer<void, U>(void*, U*) = delete;
And you must use another one:
template<typename U>
void processPointer(void*, U*) = delete;
I don't see any reason to go templating here
In fact, by deleting the non-template overload you may wiggle your way out of some edge-case ambiguous calls that I can't think of right now, since non-templates take precedence over template instantiations. And thus make this work as desired in a majority of cases.