隐式类型转换编译失败了,为什么?

3

我写了一小段代码:

#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改为explicit,则会编译失败。而无论我在s3上使用decay<char*>s2s3都无法编译通过。


问题出在是否为f指定了模板初始化参数类型。为什么s2s3无法编译通过?这在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;
}

它仍然失败了。为什么?

试着站在编译器的角度思考。请解释一下,在s2的情况下,由于函数参数是const char[6],编译器如何得出模板参数必须是char的结论。另外,你的衰减是错误的。const char[6]会衰减为const char *,而不是char * - Sam Varshavchik
1个回答

3
因为模板类型参数推导不考虑隐式转换。
引用块:
类型推导不考虑隐式转换(除了上面列出的类型调整):这是后续重载决议的工作。
对于第二种情况,编译器无法将>与匹配,函数模板在重载决议之前被忽略。
第三种情况失败是因为“Hello”(即)无法转换为decay。您可能意味着typename decay::type,但由于第二种情况的相同原因,它仍然无法编译。

如果“T”表示任何类型,为什么M<T>不能将T匹配到“const char [6]”? - Hind Forsum
@HindForsum T 可以匹配,但参数类型是 M<T>,无法匹配。 - songyuanyao

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接