My problem can be reproduced as this:
struct MyClass {
template<typename...Ts>
MyClass(Ts&&..., int) {};
};
int main() {
MyClass mc{1, 2 }; // error: cannot convert from 'initializer list' to 'MyClass'
}
What's wrong with my code?
In a primary class template, the template parameter pack must be the final parameter in the template parameter list. In a function template, the template parameter pack may appear earlier in the list provided that all following parameters can be deduced from the function arguments, or have default arguments.
Remove the last parameter in the constructor and use brackets in construction if you want to pass list of ints, not initializer_list.
template<typename...Ts>
MyClass(Ts&&...) {};
MyClass mc(1, 2);
Parameter packs (and their deduction) are greedy. When you initialize your MyClass
, the two integers go towards deducing the pack [int, int]
and the last integer is left without a corresponding argument.
This makes the c'tor not viable in overload resolution. Since your class has no other constructors that could be used here, it's a hard error.
This is one reason why a parameter pack should usually go last, if we ever want the function to be viable after template argument deduction.
struct MyClass {
template<typename...Ts>
MyClass(int, Ts&&...) {}
};
int main() {
MyClass mc{7,9,1}; // no more error
}
The reason is when you specify 'int' after 'Ts&&...' the compiler cannot deduce if the last type belongs to the parameter pack or not.
From http://en.cppreference.com/w/cpp/language/parameter_pack
In a primary class template, the template parameter pack must be the final parameter in the template parameter list. In a function template, the template parameter pack may appear earlier in the list provided that all following parameters can be deduced from the function arguments, or have default arguments:
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}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.