2013-06-07 58 views

Trả lời

37

Sự cố của bạn phải làm với aggregate initialization: struct X là tổng hợp trong khi struct Y thì không. Dưới đây là trích dẫn chuẩn về tổng hợp (8.5.1):

Tổng hợp là một mảng hoặc một lớp (Điều 9) không có nhà cung cấp do người dùng cung cấp (12.1), không có dấu ngoặc đơn hoặc bằng nhau thành viên dữ liệu không tĩnh (9.2), không có thành viên dữ liệu không được bảo mật hoặc riêng tư (Điều 11), không có lớp cơ sở (Điều 10) và không có chức năng ảo (10.3).

Điều khoản này quy định rằng nếu class có lớp cơ sở thì không phải là tổng hợp. Ở đây, struct Ystruct X làm lớp cơ sở và do đó không thể là loại tổng hợp.

Liên quan đến vấn đề cụ thể mà bạn có, lấy mệnh đề sau đây từ tiêu chuẩn:

Khi một tổng thể được khởi tạo bởi một danh sách initializer, theo quy định tại 8.5.4, các yếu tố của danh sách initializer được lấy làm người khởi tạo cho các thành viên của tổng hợp, trong việc tăng chỉ số hoặc số lượng thành viên. Mỗi thành viên được sao chép-khởi tạo từ điều khoản khởi tạo tương ứng. Nếu mệnh đề initializer-là một biểu thức và một chuyển đổi thu hẹp (8.5.4) là cần thiết để chuyển đổi biểu thức, chương trình bị hỏng.

Khi bạn làm X x = {0}, cốt liệu khởi tạo được sử dụng để khởi a-0. Tuy nhiên, khi bạn làm Y y = {0}, vì struct Y không phải là một loại tổng hợp, trình biên dịch sẽ tìm kiếm một hàm tạo thích hợp. Vì không có các hàm tạo được tạo ngầm nào (mặc định, sao chép và di chuyển) có thể làm bất cứ điều gì với một số nguyên duy nhất, trình biên dịch từ chối mã của bạn.


Về lookup này nhà thầu, các thông báo lỗi từ kêu vang ++ là một chút rõ ràng hơn về những gì các trình biên dịch được thực sự cố gắng để làm (online example):

Y Y = {0}; 
^ ~~~ 

main.cpp:5:8: note: candidate constructor (the implicit copy constructor) not viable: no known conversion from 'int' to 'const Y &' for 1st argument 

struct Y : public X {}; 
    ^

main.cpp:5:8: note: candidate constructor (the implicit move constructor) not viable: no known conversion from 'int' to 'Y &&' for 1st argument 

struct Y : public X {}; 
    ^

main.cpp:5:8: note: candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 1 was provided 

Lưu ý rằng có a proposal để mở rộng quá trình tổng hợp để hỗ trợ trường hợp sử dụng của bạn, nó được đưa vào C++ 17. Nếu tôi đọc nó một cách chính xác, nó làm cho ví dụ của bạn hợp lệ với ngữ nghĩa bạn mong đợi. Vì vậy ... bạn chỉ phải đợi trình biên dịch C++ 17 tương thích.

+1

'clang ++ -std = C++ 1z' ​​phiên bản 4.0.1 biên dịch, ' g ++ -std = C++ 17' phiên bản 7.2.1 biên dịch, nhưng Visual Studio 2017 'cl' phiên bản 19.12.25816 chưa –

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