Bạn đã gặp phải trường hợp được giải quyết theo độ phân giải Core issue 1467 ngay sau khi C++ 14 được hoàn tất.
Hãy lưu ý rằng lớp học foo
là tổng hợp. Mã của bạn đang thực hiện khởi tạo danh sách trực tiếp cho foo
. Các quy tắc cho việc khởi tạo danh sách nằm trong [8.5.4p3].
Trong C++ 14 (trích dẫn từ N4140, dự thảo làm việc gần nhất với tiêu chuẩn công bố), đoạn bắt đầu trên với:
List-initialization of an object or reference of type T
is defined as follows:
- If
T
is an aggregate, aggregate initialization is performed (8.5.1).
[...]
Vì vậy, nếu lớp học của bạn là một tổng hợp, trình biên dịch cố gắng khởi tạo tổng hợp, không thành công.
Điều này đã được công nhận là sự cố và được khắc phục trong bản nháp đang hoạt động. Trích dẫn từ phiên bản hiện tại, N4527, đoạn nêu trên hiện nay bắt đầu với:
List-initialization of an object or reference of type T
is defined as follows:
- If
T
is a class type and the initializer list has a single element of type cvU
, where U
is T
or a class derived from T
, the object is initialized from that element (by copy-initialization for copy-list-initialization, or by direct-initialization for direct-list-initialization).
- Otherwise, if
T
is a character array and the initializer list has a single element that is an appropriately typed string literal (8.5.2), initialization is performed as described in that section.
- Otherwise, if
T
is an aggregate, aggregate initialization is performed (8.5.1).
[...]
dụ của bạn bây giờ nằm trong trường hợp được mô tả bởi các điểm viên đạn đầu tiên, và foo
là trực tiếp-list-khởi sử dụng hàm tạo bản sao mặc định (bất kể đó là explicit
, vì nó khởi tạo trực tiếp).
Đó là ... nếu trình biên dịch thực hiện độ phân giải trong báo cáo lỗi.
- GCC 5.2.0 (và 6.0.0 trunk) có vẻ như vậy, nhưng dường như có lỗi liên quan đến số
explicit
.
- Clang 3.6.0 không, nhưng 3.8.0 thân cây, và làm nó một cách chính xác (
explicit
không quan trọng).
- MSVC 14, nhưng IntelliSense trong IDE không (squiggles dưới
bar
- trông giống như trình biên dịch EDG được sử dụng bởi IntelliSense không được cập nhật).
Cập nhật: Kể từ khi câu trả lời này được viết ra, dự thảo làm việc đã được sửa đổi hơn nữa trong một vài cách có liên quan đến ví dụ trong câu hỏi và giải thích ở trên:
- CWG 2137 chỉ ra rằng viên đạn đầu tiên trong đoạn trích dẫn ở trên đã đi quá xa một chút bằng cách áp dụng ngoại lệ đó cho tất cả các loại lớp (ghi chú vấn đề chứa một ví dụ liên quan). Sự khởi đầu của viên đạn bây giờ đọc:
- If
T
is an aggregate class and [...]
- Độ phân giải của CWG 1518 chứa trong giấy P0398R0 chỉ ra rằng lớp tuyên bố một
explicit
constructor (thậm chí defaulted) không còn uẩn.
Điều này không thay đổi thực tế là, sau khi tất cả thay đổi được thực hiện, ví dụ trong câu hỏi được dự định làm việc, có hoặc không có explicit
; nó chỉ là giá trị biết rằng các cơ chế cơ bản mà làm cho nó hoạt động đã thay đổi một chút.
Lưu ý rằng tất cả những thay đổi này là độ phân giải của các báo cáo lỗi, vì vậy chúng phải được áp dụng khi các trình biên dịch cũng ở chế độ C++ 14 và C++ 11.
clang hiển thị lỗi ngay cả khi không có từ khóa 'clear' http://coliru.stacked-crooked.com/a/1cca94237ee00ea3 – Steephen
@Stephen thực sự, tôi không thấy điều đó. Vì vậy, nó là một câu hỏi kiểu ngôn ngữ-luật sư sôi nổi :) – vsoftco
Tôi sẽ nói rằng trình biên dịch chọn để tổng hợp khởi tạo 'foo'. – Jarod42