这段代码编译得很好:
template <typename T1>
struct Struct {
};
struct ConvertsToStruct {
operator Struct<int>() const;
};
template <typename T>
void NonVariadicFunc(Struct<T>);
int main() {
NonVariadicFunc<int>(ConvertsToStruct{});
return 0;
}
但试图通过使用可变参数模板使其更通用一些,但编译失败:
template <typename T1>
struct Struct {
};
struct ConvertsToStruct {
operator Struct<int>() const;
};
template <typename... T>
void VariadicFunc(Struct<T...>);
int main() {
VariadicFunc<int>(ConvertsToStruct{});
return 0;
}
怎么了?为什么我尝试显式指定 VariadicFunc
的模板类型没有成功?
Godbolt 链接 => https://godbolt.org/g/kq9d7L
最佳答案
有两个原因可以解释为什么这段代码无法编译。
首先,模板函数的模板参数可以部分指定:
template<class U, class V> void foo(V v) {}
int main() {
foo<double>(12);
}
此代码有效,因为您指定了第一个模板参数 U
并让编译器确定第二个参数。出于同样的原因,你的 VariadicFunc<int>(ConvertsToStruct{});
还需要模板参数推导。这是一个类似的例子,它编译:
template<class... U> void bar(U... u) {}
int main() {
bar<int>(12.0, 13.4f);
}
现在我们知道编译器需要对你的代码进行推导,接下来是第二部分:编译器按照固定的顺序处理不同的阶段:
Template argument deduction takes place after the function template name lookup (which may involve argument-dependent lookup) and before template argument substitution (which may involve SFINAE) and overload resolution.
隐式转换发生在重载解析时,在 模板参数推导之后。因此,在您的情况下,当编译器进行模板参数推导时,用户定义的转换运算符的存在无效。显然ConvertsToStruct
本身无法匹配任何东西,因此推导失败,代码无法编译。
关于c++ - 为什么只有一个参数的可变参数模板与非可变参数模板不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48630866/