为什么我的可变参数模板构造函数与其参数不匹配?

时间:2018-03-18 06:40:04

标签: c++ c++11 visual-c++

我的问题可以这样重现:

struct MyClass {
    template<typename...Ts>
    MyClass(Ts&&..., int) {};
};

int main() {
    MyClass mc{1, 2 }; // error: cannot convert from 'initializer list' to 'MyClass'
}

我的代码出了什么问题?

3 个答案:

答案 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}