2014-06-05 40 views
6

Tôi có câu hỏi liên quan đến thủ tục khấu trừ loại tham số mẫu chức năng.Dấu ngoặc đơn-init-danh sách và thứ tự khấu trừ loại mẫu chức năng

Hãy ví dụ này:

#include <vector> 
#include <sstream> 
#include <string> 
#include <iterator> 
#include <fstream> 

int main() 
{ 
    std::ifstream file("path/to/file"); 
    std::vector<int> vec(std::istream_iterator<int>{file},{}); // <- This part 
    return 0; 
} 

Nếu tôi hiểu được những điều đúng, tham số thứ hai là suy luận là loại std::istream_iterator trong đó constructor mặc định được gọi.

Thích hợp std::vector constructor được khai báo là:

template <class InputIterator> 
     vector (InputIterator first, InputIterator last, 
       const allocator_type& alloc = allocator_type()); 

Kể từ kiểu tham số đầu tiên là suy luận như std::istream_iterator<int> tham số thứ hai là suy luận như std::istream_iterator<int> quá và vì vậy ngữ nghĩa khởi thống nhất có thể được áp dụng. Những gì tôi không có ý tưởng về là những gì để loại khấu trừ xảy ra. Tôi thực sự sẽ đánh giá cao một số thông tin về điều này.

Cảm ơn trước!

+0

Tính năng này có hoạt động không? Nếu như vậy đầu tiên phải được khấu trừ đầu tiên. – Dani

Trả lời

9

Hãy sử dụng một ví dụ thậm chí đơn giản hơn:

template<class T> 
void foo(T, T); 

foo(42, {}); 

Cuộc gọi hàm có hai tham số:

  • một biểu prvalue loại int (một số nguyên theo nghĩa đen)
  • một chuẩn bị tinh thần-init -list{}

Sau này, {}, có thể là một phần của danh sách biểu hiện nhưng không phải là biểu hiện . An biểu thức danh sách được định nghĩa là một danh sách khởi tạo . braced-init-lists không có loại.

Loại trừ mẫu được thực hiện cho từng tham số chức năng riêng lẻ [temp.deduct.type]/2. [Temp.deduct.call]/1 quốc gia về loại trừ cho một tham số chức năng P:

Nếu loại bỏ tài liệu tham khảo và cv-vòng loại từ P cho std::initializer_list<P '> đối với một số P' và đối số là một danh sách initializer, sau đó khấu trừ được thực hiện thay cho mỗi phần tử của danh sách khởi tạo, lấy P' như một hàm mẫu tham số loại và các yếu tố khởi tạo như là đối số của nó. Nếu không, một đối số của đối số khởi tạo sẽ làm cho thông số được coi là một ngữ cảnh không được suy luận . [tôi nhấn mạnh]

Vì vậy, trong cuộc gọi foo(42, {}); các T sẽ không được suy ra từ số thứ hai {}. Tuy nhiên, T có thể được suy luận từ đối số đầu tiên.

Nói chung, chúng tôi có thể suy ra T từ nhiều thông số chức năng. Trong trường hợp đó, các loại suy luận phải khớp chính xác với [temp.deduct.type]/2. Không có vấn đề nếu loại chỉ được suy ra từ một tham số chức năng nhưng được sử dụng ở nơi khác (trong một tham số hàm khác trong ngữ cảnh không suy luận, trong kiểu trả về, vv). Loại khấu trừ có thể không thành công, ví dụ: khi tham số mẫu không thể được suy ra từ bất kỳ thông số chức năng nào và không được đặt rõ ràng.

Sau khi khấu trừ, T sẽ được thay thế bởi int, sản xuất một chức năng chữ ký tương tự như:

void foo<int>(int, int); 

Chức năng này có thể được gọi với hai đối số 42{}. Sau này sẽ thực hiện khởi tạo danh sách sao chép dẫn đến việc khởi tạo giá trị của tham số thứ hai.

+0

Đây là nhiều hơn hoặc ít hơn như thế nào tôi đã nhìn thấy nó một cách trực quan. Cảm ơn bạn đã xóa mọi thứ. – Veritas

Các vấn đề liên quan