2016-12-03 31 views
36

C++ 17 giới thiệu "hướng dẫn khấu trừ mẫu". Tôi thu thập họ là một cái gì đó để làm với việc khấu trừ mẫu mới cho các nhà xây dựng được giới thiệu trong phiên bản này của tiêu chuẩn, nhưng tôi chưa nhìn thấy một lời giải thích đơn giản, Câu hỏi thường gặp về những gì họ đang có và những gì họ đang có.Hướng dẫn khấu trừ mẫu là gì và khi nào chúng tôi nên sử dụng chúng?

  • Hướng dẫn khấu trừ mẫu trong C++ 17 là gì?

  • Tại sao (và khi nào) chúng tôi cần chúng?

  • Làm cách nào để khai báo?

+3

http://en.cppreference.com/w/cpp/language/class_template_deduction – doug

+0

Cụ thể, tôi muốn được quan tâm để biết liệu bất kỳ hướng dẫn khấu trừ nào thực sự được cung cấp bởi C++ 17 STL (ví dụ: đối với std: : pair hoặc std :: tuple). Danh sách đầy đủ các loại mẫu tiêu chuẩn "có thể khấu trừ" là C++ 17 là bao nhiêu? – Quuxplusone

+0

@Quuxplusone http://en.cppreference.com/w/cpp/utility/pair/deduction_guides và http: //en.cppreference.com/w/cpp/utility/tuple/deduction_guides – Cubbi

Trả lời

46

Hướng dẫn khấu trừ mẫu là các mẫu được liên kết với một lớp mẫu cho trình biên dịch biết cách dịch tập hợp tham số (và loại của chúng) thành đối số mẫu.

Ví dụ đơn giản nhất là của std::vector và hàm tạo của nó có cặp lặp.

template<typename Iterator> 
void func(Iterator first, Iterator last) 
{ 
    vector v(first, last); 
} 

Trình biên dịch cần tìm ra loại T sẽ là loại nào. Chúng tôi biết câu trả lời là gì; T phải là typename std::iterator_traits<Iterator>::value_type. Nhưng làm cách nào để chúng tôi thông báo cho trình biên dịch mà không cần phải nhập vector<typename std::iterator_traits<Iterator>::value_type>?

Bạn sử dụng một hướng dẫn khấu trừ:

template<typename Iterator> vector(Iterator b, Iterator e) -> 
    vector<typename std::iterator_traits<Iterator>::value_type>; 

này cho trình biên dịch rằng, khi bạn gọi một constructor vector phù hợp với mô hình đó, nó sẽ suy ra vector chuyên môn hóa bằng cách sử dụng mã trên bên phải của ->.

Bạn cần hướng dẫn khi khấu trừ loại từ đối số không dựa trên loại của một trong các đối số đó. Khởi tạo một vector từ một initializer_list sử dụng rõ ràng vector 's T, vì vậy nó không cần hướng dẫn.

Phía bên trái không nhất thiết phải chỉ định một hàm tạo. Cách thức hoạt động của nó là, nếu bạn sử dụng khấu trừ constructor mẫu trên một kiểu, nó khớp với các đối số bạn vượt qua đối với tất cả các hướng dẫn khấu trừ (các hàm tạo thực tế cung cấp các hướng dẫn ngầm). Nếu có một kết quả phù hợp, nó sử dụng nó để xác định các đối số mẫu nào cần cung cấp cho loại đó. Nhưng độ phân giải quá tải để xác định hàm khởi tạo nào sẽ xảy ra sau đó.

này cũng có nghĩa là bạn có thể sử dụng hướng dẫn với uẩn và khởi tạo tổng hợp:

template<typename T> 
struct Thingy 
{ 
    T t; 
}; 

Thingy(const char *) -> Thingy<std::string>; 

Thingy thing{"A String"}; //thing.t is a `std::string`. 

Vì vậy, hướng dẫn khấu trừ chỉ được sử dụng để tìm ra các loại đang được khởi tạo. Quá trình khởi tạo thực sự hoạt động chính xác như trước đây, một khi quyết định đó đã được thực hiện.

+3

Hmm, nó chỉ xảy ra với tôi rằng ngay cả với hướng dẫn, 'vectơ v {đầu tiên, cuối cùng};' sẽ không làm điều đúng: ( –

+6

@TC: Đó là " khởi tạo thống nhất "cho bạn. –

+0

@TC ... trừ khi điều đúng là tạo một vectơ của các trình lặp. Và' 'std :: string {32, '*'} [0] == ''' '(cho ASCII). điều này tất cả đều đúng vì C++ 11. –

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