我的问题可以这样重现:
struct MyClass {
template<typename...Ts>
MyClass(Ts&&..., int) {};
};
int main() {
MyClass mc{1, 2 }; // error: cannot convert from 'initializer list' to 'MyClass'
}
我的代码出了什么问题?
答案 0 :(得分:0)
在主类模板中,模板参数包必须是模板参数列表中的最后一个参数。在函数模板中,模板参数包可以出现在列表的前面,前提是所有后续参数都可以从函数参数中推导出来,或者具有默认参数。
如果要传递整数列表而不是initializer_list,请删除构造函数中的最后一个参数并在构造中使用括号。
template<typename...Ts>
MyClass(Ts&&...) {};
MyClass mc(1, 2);
答案 1 :(得分:0)
参数包(及其推论)是贪婪的。初始化MyClass
时,两个整数将用于推导包[int, int]
,最后一个整数没有相应的参数。
这使得c'tor在重载分辨率方面不可行。由于你的类没有其他可以在这里使用的构造函数,所以这是一个很难的错误。
如果我们希望在模板参数扣除后函数可行,这就是参数包通常应该最后的一个原因。
答案 2 :(得分:0)
struct MyClass {
template<typename...Ts>
MyClass(int, Ts&&...) {}
};
int main() {
MyClass mc{7,9,1}; // no more error
}
原因是当你在'Ts&amp;&amp; ...'之后指定'int'时,编译器无法推断出最后一个类型是否属于参数包。
来自http://en.cppreference.com/w/cpp/language/parameter_pack
在主类模板中,模板参数包必须是 模板参数列表中的最后一个参数。在一个功能 模板,模板参数包可能会出现在列表的前面 只要可以从中推导出以下所有参数 函数参数,或者有默认参数:
template<typename... Ts, typename U> struct Invalid; // Error: Ts.. not at the end
template<typename ...Ts, typename U, typename=void>
void valid(U, Ts...); // OK: can deduce U
// void valid(Ts..., U); // Can't be used: Ts... is a non-deduced context in this position
valid(1.0, 1, 2, 3); // OK: deduces U as double, Ts as {int,int,int}