Home > Software engineering >  Wrong overload selected when implicity converting to a const type
Wrong overload selected when implicity converting to a const type

Time:09-25

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:

  1. Either to instantiate a function from template which will be able (potentially) to change the value.
  2. 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.

  • Related