Cuộc gọi đầu tiên f(12)
bị ốm - hình thành. Một tham số-pack mà không xuất hiện ở phần cuối của một tham số khai báo là một bối cảnh phi suy luận mỗi [temp.deduct.type] /p5.7:
The non-deduced contexts are:
— [..]
— A function parameter pack that does not occur at the end of the parameter-declaration-list
Tiếp tục trong [temp.deduct.call ]/p1:
For a function parameter pack that occurs at the end of the parameter-declaration-list, the type A
of each remaining argument of the call is compared with the type P
of the declarator-id of the function parameter pack. Each comparison deduces template arguments for subsequent positions in the template parameter packs expanded by the function parameter pack. When a function parameter pack appears in a non-deduced context (14.8.2.5), the type of that parameter pack is never deduced.
[ Example:
template<class ... Types> void f(Types& ...);
template<class T1, class ... Types> void g(T1, Types ...);
template<class T1, class ... Types> void g1(Types ..., T1);
void h(int x, float& y) {
const int z = x;
f(x, y, z); // Types is deduced to int, float, const int
g(x, y, z); // T1 is deduced to int; Types is deduced to float, int
g1(x, y, z); // error: Types is not deduced
g1<int, int, int>(x, y, z); // OK, no deduction occurs
}
— end example ]
Vì vậy, các thông số gói X...
không thể được suy luận bởi đối số của hàm và khấu trừ mẫu đối số thất bại. GCC chấp nhận cuộc gọi đầu tiên thay vì từ chối mẫu để không khấu trừ 12
do đó, nó dường như là một lỗi.
Cuộc gọi thứ hai, f<int, int, int>(1, 2, 3, 4)
, tuy nhiên, được định dạng đúng theo [temp.deduct]/p6. Các đối số mẫu được chỉ định rõ ràng được thay thế ngay lập tức cho các tham số mẫu của mẫu hàm. Điều này có nghĩa là X = {int, int, int}
. trích lập luận mẫu sau đó tiến hành với Y
được rút ra từ những tranh cãi ngoài cùng bên phải như int
:
At certain points in the template argument deduction process it is necessary to take a function type that makes use of template parameters and replace those template parameters with the corresponding template arguments. This is done at the beginning of template argument deduction when any explicitly specified template arguments are substituted into the function type, and again at the end of template argument deduction when any template arguments that were deduced or obtained from default arguments are substituted.
Lưu ý rằng cũng ([temp.deduct]/p2):
There must not be more arguments than there are parameters unless at least one parameter is a template parameter pack, and there shall be an argument for each non-pack parameter.
Clang không chấp nhận các chức năng cuối cùng gọi, nhưng GCC có. Tôi tin rằng đây là một lỗi Clang.
Lưu ý rằng có một mở CWG issue 1609 liên quan đến việc sử dụng đối số mặc định sau khi xảy ra gói tham số. Ngoài ra còn có LLVM Bug 21774 để tranh chấp hành vi của Clang trong bối cảnh đó.
Các cuộc gọi có được tối ưu hóa không? –