Reputation: 23
I have problems with specialized function templates in C++. I'm writing a comparison function template which will be used in sorting different data types. Here is part of my code:
template < typename T >
bool cmp(T a, T b)
{
std::cout<<"normal"<<std::endl;
return(a >= b);
}
template < typename T >
bool cmp(T* a, T* b)
{
std::cout<<"pointer"<<std::endl;
return(*a >= *b);
}
so I could sort by values and by pointed values. However, when I try to pass this function into sort
:
double* double_array[]={d1,d2,d3,d4,d5};
nsp::sort(double_array, 5, nsp::cmp<double*>);
I get the compile error:
error: no matching function for call to 'sort(double* [5], int, <unresolved overloaded function type>)'|
template argument deduction/substitution failed:|
could not resolve address from overloaded function 'cmp<double*>'|
Why? I am explicitly providing the template type!
For reference, my sort function template looks like:
namespace nsp {
...
template < typename T, typename CMP>
void sort(T array[], int n, CMP cmp=CMP())
{
for(int j = 0;j < n-1; j++)
for(int i = 0; i < n-1; i++)
if(cmp(array[i],array[i + 1]))
std::swap(array[i], array[i + 1]);
}
}
Upvotes: 1
Views: 886
Reputation: 303017
The reason you're getting a compile error with "unresolved overloaded function type" is because, quite simply, you are trying to pass an overloaded function to sort()
. You provide cmp<double*>
but there are still two cmp<double*>
functions: the fun that takes two double*
s (your first function template) and the one that takes two double**
s (your second). It's unclear to the compiler which one you mean.
You could just cast cmp
to the one that you want:
static_cast<bool(*)(double*, double*)>(nsp::cmp<double>) // note you want cmp<double>,
// not cmp<double*>
Note that one source of confusion is that you think you are specializing cmp
. You are not. There is no partial specializations of function templates. You overloaded it. The only allowed specializations of function templates are explicit:
template <>
bool cmp(double* a, double* b) {
std::cout<<"pointer"<<std::endl;
return(*a >= *b);
}
That would make nsp::cmp<double*>
unambiguous and would do exactly what you would expect. In this case. You would have to do this for every type separately. Instead, you could provide a class template comparator because class templates can be partially specialized:
template <typename T> struct Cmp { .. }; // "normal"
template <typename T> struct Cmp<T*> { .. }; // "pointer"
That way, you can just pass nsp::Cmp<double*>()
, which is in my opinion much cleaner.
Upvotes: 3