Trong thời đại khai sáng năm 2016, với hai tiêu chuẩn mới của chúng tôi kể từ khi câu hỏi này được đặt ra và một tiêu chuẩn mới sắp xuất hiện, điều quan trọng cần biết là các trình biên dịch hỗ trợ tiêu chuẩn C ++ 17 sẽ biên dịch mã của bạn như hiện tại. .
Khấu trừ đối số mẫu cho các mẫu lớp trong C ++ 17
Đây (với sự chỉnh sửa của Olzhas Zhumabek về câu trả lời được chấp nhận) là bài báo trình bày chi tiết những thay đổi liên quan đối với tiêu chuẩn.
Giải quyết mối quan tâm từ các câu trả lời khác
Câu trả lời được xếp hạng hàng đầu hiện tại
Câu trả lời này chỉ ra rằng "phương thức tạo bản sao và operator=
" sẽ không biết các chuyên ngành mẫu chính xác.
Điều này là vô nghĩa, bởi vì hàm tạo bản sao tiêu chuẩn và operator=
chỉ tồn tại cho một loại mẫu đã biết :
template <typename T>
class MyClass {
MyClass(const MyClass&) =default;
... etc...
};
// usage example modified from the answer
MyClass m(string("blah blah blah"));
MyClass *pm; // WHAT IS THIS?
*pm = m;
Ở đây, như tôi đã lưu ý trong các ý kiến, có không có lý do để MyClass *pm
trở thành một tuyên bố pháp lý có hoặc không có các hình thức mới của suy luận: MyClass
không phải là một loại (đó là một mẫu), do đó nó không có ý nghĩa để khai báo một con trỏ của loại MyClass
. Đây là một cách có thể để sửa ví dụ:
MyClass m(string("blah blah blah"));
decltype(m) *pm; // uses type inference!
*pm = m;
Dưới đây, pm
là đã về đúng loại, và do đó suy luận là tầm thường. Hơn nữa, không thể vô tình trộn các kiểu khi gọi hàm tạo bản sao:
MyClass m(string("blah blah blah"));
auto pm = &(MyClass(m));
Đây, pm
sẽ là một con trỏ đến một bản sao của m
. Ở đây, MyClass
đang được sao chép xây dựng từ m
— loại nào MyClass<string>
(và không thuộc loại không tồn tại MyClass
). Do đó, tại điểm mà pm
's loại được suy ra, có là đủ thông tin để biết rằng mẫu-loại m
, và do đó mẫu-loại pm
, là string
.
Hơn nữa, phần sau sẽ luôn phát sinh lỗi biên dịch :
MyClass s(string("blah blah blah"));
MyClass i(3);
i = s;
Điều này là do khai báo của hàm tạo bản sao không được tạo mẫu:
MyClass(const MyClass&);
Ở đây, kiểu mẫu của đối số copy-constructor khớp với kiểu mẫu của lớp nói chung; tức là, khi nào MyClass<string>
được khởi tạo, MyClass<string>::MyClass(const MyClass<string>&);
được khởi tạo cùng với nó, và khi nào MyClass<int>
được khởi tạo, MyClass<int>::MyClass(const MyClass<int>&);
được khởi tạo. Trừ khi nó được chỉ định rõ ràng hoặc một phương thức khởi tạo được tạo mẫu được khai báo, không có lý do gì để trình biên dịch khởi tạo MyClass<int>::MyClass(const MyClass<string>&);
, điều này rõ ràng là không phù hợp.
Câu trả lời của Cătălin Pitiș
Pitiș đưa ra một ví dụ về suy luận Variable<int>
và Variable<double>
sau đó nói:
Tôi có cùng một tên loại (Biến) trong mã cho hai loại khác nhau (Biến và Biến). Theo quan điểm chủ quan của tôi, nó ảnh hưởng khá nhiều đến khả năng đọc của mã.
Như đã lưu ý trong ví dụ trước, Variable
bản thân nó không phải là một tên kiểu, mặc dù tính năng mới làm cho nó giống như một cú pháp.
Pitiș sau đó hỏi điều gì sẽ xảy ra nếu không có hàm tạo nào được đưa ra để cho phép suy luận thích hợp. Câu trả lời là không cho phép suy luận, bởi vì suy luận được kích hoạt bởi lời gọi hàm tạo . Không có lời gọi hàm tạo, không có suy luận .
Điều này tương tự như hỏi phiên bản nào foo
được suy ra ở đây:
template <typename T> foo();
foo();
Câu trả lời là mã này là bất hợp pháp, vì lý do đã nêu.
Câu trả lời của MSalter
Theo như tôi có thể nói thì đây là câu trả lời duy nhất để đưa ra mối quan tâm chính đáng về tính năng được đề xuất.
Ví dụ là:
Variable var(num); // If equivalent to Variable<int> var(num),
Variable var2(var); // Variable<int> or Variable<Variable<int>> ?
Câu hỏi quan trọng là, trình biên dịch chọn hàm tạo suy ra kiểu ở đây hay hàm tạo sao chép ?
Thử mã ra, chúng ta có thể thấy rằng hàm tạo bản sao đã được chọn. Để mở rộng ví dụ :
Variable var(num); // infering ctor
Variable var2(var); // copy ctor
Variable var3(move(var)); // move ctor
// Variable var4(Variable(num)); // compiler error
Tôi không chắc đề xuất và phiên bản mới của tiêu chuẩn quy định điều này như thế nào; nó dường như được xác định bởi "hướng dẫn khấu trừ", là một chút tiêu chuẩn mới mà tôi chưa hiểu.
Tôi cũng không chắc tại sao var4
khoản khấu trừ là bất hợp pháp; lỗi trình biên dịch từ g ++ dường như chỉ ra rằng câu lệnh đang được phân tích cú pháp như một khai báo hàm.