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?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With