我写了一个小代码:
#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;
}
好吧,第一个s1
成功编译,虽然如果我将M::M
改为显式,它也将失败。但是s2
和s3
无法编译,即使我在decay<char*>
上使用s3
。
区别在于我是否为f
指定了模板初始化参数类型。为什么s2
和s3
无法编译,C ++标准中的任何原则?
如果我将main函数改为这样:
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;
}
它仍然失败。
为什么?
因为template type argument deduction不考虑隐式转换。
类型推导不考虑隐式转换(上面列出的类型调整除外):这是重载解析的工作,稍后会发生。
对于第二种情况,编译器无法将M<T>
与const char [6]
匹配,函数模板在重载解析之前就被忽略了。
第三种情况失败,因为"Hello"
(即const char [6]
)无法转换为decay<char *>
。你可能意味着typename decay<char*>::type
,但它仍然无法编译出于第二种情况的相同原因。