Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implicit type conversion failed to compile, why is that?

I wrote a small code:

#include<type_traits>

using namespace std;

template<typename T>
struct M{
    /*explicit*/ M(const T*) {}
};

template<typename T>
M<T> f(const M<T>&) {return M<T>();}

int main() {
    M<char> s1 = f<char>("Hello"); // OK
    M<char> s2 = f("Hello"); // error
    M<char> s3 = f(decay<char*>("Hello")); // error
    return 0;
}

Well the first s1 successfully compiles, although if I change M::M to explicit, it will also fail. But s2 and s3 fail to compile, even when I use decay<char*> on s3.


The difference is whether I specified template initialization argument type for f or not. Why do s2 and s3 fail to compile, any principles behind this in the C++ standard?

If I change main function to like this:

int main()
{
    M<char> s1=f<char>("Hello");//OK
    const char* p="hello";
    M<char> s2=f(p);//error
    M<char> s3=f(decay<const char*>("Hello"));//error
    return 0;
}

It still fails.

Why?

like image 783
Hind Forsum Avatar asked Feb 10 '26 21:02

Hind Forsum


1 Answers

Because template type argument deduction does not consider implicit conversions.

Type deduction does not consider implicit conversions (other than type adjustments listed above): that's the job for overload resolution, which happens later.

For the 2nd case, compiler can't match M<T> with const char [6], the function template is just ignored before overload resolution.

The 3rd case fails because "Hello" (i.e. const char [6]) can't be converted to decay<char *>. You might mean typename decay<char*>::type, but it still won't compile for the same reason of the 2nd case.

like image 74
songyuanyao Avatar answered Feb 12 '26 14:02

songyuanyao



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!