Consider the code below:
#include <iostream>
// General overload using a template
template <typename SomeType>
void some_func(const SomeType p) {
std::cout << "Using the general function" << std::endl;
}
// Specific overload, accepting a 'const double*' type
void some_func(const double* p) {
std::cout << "Using the function accepting a const double*" << std::endl;
}
int main() {
// This one uses the specific overload, as expected
const double *a = new double(1.1);
some_func(a);
delete a;
// This one uses the general function rather than the second overload
double *b = new double(1.1);
some_func(b);
delete b;
return 0;
}
In this piece of code, there are two overloads of the some_func
function. The first one is the most general overload, using a template to capture practically any type. The second overload is a specific overload, accepting a const double*
type as its argument.
In the main
function, I first create the variable a
of type const double*
. When supplying a
to some_func
, the second overload is selected. This is as expected. Secondly, I create a variable b
of type double*
(so no const
). When supplying the variable b
to some_func
, it selects the first overload. I would've expected it to select the second overload, as (I think) it should be able to implicitly convert a type double*
to const double*
. Why does it select the first overload rather than the second overload in this case?
For completeness, this is the output of the program:
$ g main.cpp
$ ./a.out
Using the function accepting a const double*
Using the general function
CodePudding user response:
During template instantiation, this const SomeType p
would turn into double* const p
which is a better match than const double*
. That is, the template's parameter would become a const-pointer to mutable data.
In the template function, you can actually modify the data through that pointer, so it can be assumed it is a better match.
If you change const SomeType p
to const SomeType* p
, the specific overload will be selected.
CodePudding user response:
The qualifier const
is a kind of a contract. Here is means that the function won't be able to change the value by the pointer
So the compiler has two options:
- Either to instantiate a function from template which will be able (potentially) to change the value.
- Use the stricter function that won't be able to change it.
Having the argument which could be changed, it is logical to choose the first case.
So, following the rule of selecting with precise type, taking into account CV-qualifiers very logical.