Nói chung, để khấu trừ thành công, đối số cần phải có cùng một dạng chung như tham số. Có một số ngoại lệ trong đó T &&
có thể được suy ra từ U &
(bằng cách chọn T = U &
), nhưng không có trường hợp ngoại lệ nào được chỉ định cho trường hợp này.
14.8.2.5 Suy luận đối số mẫu từ một loại [temp.deduct.type]
8 Mẫu kiểu lập luận T
, một mẫu template luận TT
hoặc một đối số mẫu không loại i
có thể suy luận nếu P
và A
có một trong các hình thức sau:
[...]
T&
T&&
[...]
Nó không phải chính xác rõ ràng, nhưng điều này đòi hỏi P
(tham số) và A
(đối số) để cả hai đều có hình thức tương tự. Cả hai cần phải có dạng T&
hoặc cả hai dạng T&&
.Các trường hợp ngoại lệ, các trường hợp T &&
có thể được rút ra từ U &
, được thực hiện bằng cách thay đổi T &&
để đồng bằng T
trước khớp diễn ra, trong trường hợp hạn chế:
10 Tương tự, nếu P
có một hình thức có chứa (T)
, sau đó mỗi loại thông số Pi
của danh sách loại tương ứng của P
được so sánh với loại thông số tương ứng Ai
của thông số tương ứng tương ứng của A
. Nếu P
và A
là các loại chức năng có nguồn gốc từ khấu trừ khi lấy địa chỉ của mẫu chức năng (14.8.2.2) hoặc khi khấu trừ đối số mẫu từ khai báo hàm (14.8.2.6) và Pi
và Ai
là thông số của cấp cao nhất tham số kiểu-list của P
và A
, tương ứng, Pi
được điều chỉnh nếu nó là một tài liệu tham khảo rvalue đến một tham số mẫu cv-không đủ tiêu chuẩn và Ai
là một tài liệu tham khảo giá trị trái, trong trường hợp này loại Pi
được thay đổi để trở thành mẫu loại thông số (ví dụ: T&&
được thay đổi thành chỉ đơn giản là T
). [...]
và
14.8.2.1 Suy luận đối số mẫu từ một cuộc gọi chức năng [temp.deduct.call]
3 [...] Nếu P
là một tham chiếu rvalue cho một tham số mẫu cv-unqualified và đối số là một giá trị, loại "tham chiếu lvalue đến A
" được sử dụng thay cho A
để khấu trừ loại. [...]
nhưng không có ngoại lệ tương tự nào áp dụng cho trường hợp của bạn.
Đó là nguyên tắc này tương tự mà làm cho
template <typename T> struct S { };
template <typename T> void f(S<const T>) { }
int main() { f(S<void()>()); }
không hợp lệ: const T
không thể được rút ra từ void()
, mặc dù T = void()
sẽ cung cấp chính xác những kết quả đó, và gọi f<void()>
sẽ thành công.
câu trả lời đã xóa Wintermute cho thấy rằng bạn có thể sử dụng
template <typename... Types> // vv-- change here
void print_tuple(const std::tuple<Types...>& value)
thay vì: điều này cho phép Types
được suy luận như tài liệu tham khảo giá trị trái, như tài liệu tham khảo rvalue, hoặc như phi tài liệu tham khảo, tùy thuộc vào loại value
.
Bạn thậm chí không cần chụp một bộ dữ liệu cụ thể. Tại sao không đơn giản là 'template void print_tuple (Tuple && value)'? –
0x499602D2
Vì nó không rõ ràng với ít nhất hai người: định nghĩa 'print_tuple' * của bạn * cho phép cuộc gọi nếu các đối số mẫu được chỉ định rõ ràng là' print_tuple '. Đó là một câu hỏi hay giải thích tại sao trình biên dịch lại suy ra 'Loại' đầu tiên khác nhau. –
hvd
@hvd Có thể là do một chuỗi ký tự là một giá trị và được chuyển tiếp như vậy. – 0x499602D2