Hướng dẫn suy diễn 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 một tập hợp các đối số của phương thức khởi tạo (và các kiểu của chúng) thành các tham số mẫu cho lớp.
Ví dụ đơn giản nhất là của std::vector
và hàm tạo của nó nhận một cặp trình vòng lặp.
template<typename Iterator>
void func(Iterator first, Iterator last)
{
vector v(first, last);
}
Trình biên dịch cần phải tìm ra những gì vector<T>
's T
loại sẽ. Chúng tôi biết câu trả lời là gì; T
nên được typename std::iterator_traits<Iterator>::value_type
. Nhưng làm thế nào để chúng ta nói với trình biên dịch mà không cần phải gõ vector<typename std::iterator_traits<Iterator>::value_type>
?
Bạn sử dụng hướng dẫn khấu trừ:
template<typename Iterator> vector(Iterator b, Iterator e) ->
vector<typename std::iterator_traits<Iterator>::value_type>;
Điều này cho trình biên dịch biết rằng, khi bạn gọi một hàm vector
tạo phù hợp với mẫu đó, nó sẽ suy ra sự vector
chuyên môn hóa bằng cách sử dụng mã ở bên phải của ->
.
Bạn cần hướng dẫn khi loại trừ kiểu khỏi các đối số không dựa trên kiểu của một trong những đối số đó. Khởi tạo a vector
từ một initializer_list
cách rõ ràng sử dụ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 phương thức khởi tạo thực tế. Cách hoạt động của nó là, nếu bạn sử dụng phép suy diễn hàm tạo mẫu trên một kiểu, nó sẽ khớp với các đối số mà bạn chuyển với tất cả các hướng dẫn suy luận (các hàm tạo thực tế của mẫu chính cung cấp hướng dẫn ngầm). Nếu có một kết quả phù hợp, nó sẽ sử dụng điều đó để xác định đối số mẫu nào cần cung cấp cho loại.
Nhưng một khi việc khấu trừ đó được thực hiện, khi trình biên dịch tìm ra các tham số khuôn mẫu cho kiểu, quá trình khởi tạo cho đối tượng của kiểu đó sẽ tiến hành như thể không có điều gì xảy ra. Nghĩa là, hướng dẫn khấu trừ được chọn không phải khớp với hàm tạo đã chọn.
Điều này cũng có nghĩa là bạn có thể sử dụng các hướng dẫn với tổng hợp 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"};
Vì vậy, các hướng dẫn khấu trừ chỉ được sử dụng để tìm ra kiểu đang được khởi tạo. Quá trình khởi tạo thực tế hoạt động chính xác như nó đã làm trước đây, khi quyết định đó đã được thực hiện.