2015-11-04 12 views
12

Làm thế nào để giải thích sự khác biệt, khi tôi biên dịch #if 0#if 1 phiên bản của đoạn mã sau:Explicit constructor mặc định defaulted và tập hợp

#include <cstdlib> 

struct A 
{ 
    explicit A() = default; // explicitly defaulted or deleted constructors are allowed for aggregates (since C++11) 
#if 1 
private : 
#endif 
    int i; 
}; 

int 
main() 
{ 
    A a = {}; 
    return EXIT_SUCCESS; 
} 
  • cho #if 0 tất cả là tốt, biên soạn thành công.
  • cho #if 1 biên soạn thất bại với thông báo lỗi:

    error: chosen constructor is explicit in copy-initialization

sự khác biệt cho biểu A a = {}; tuỳ thuộc vào việc A là aggreagate hay không là gì?

+2

Tôi nghĩ bạn đã tự trả lời. Khi bạn nhận được lỗi A không phải là một cấu trúc tổng hợp. Vì vậy, bạn không thể khởi tạo nó bằng cách sử dụng danh sách khởi tạo. – Jonathan

+0

@Jonathan Sự hiểu biết của riêng tôi (câm "nó phụ thuộc vào sự tổng hợp") không phải là khá rõ ràng. Tôi muốn nghe lời giải thích chính xác. – Orient

Trả lời

8

TL; DR: Clang và GCC sai khi từ chối mã của bạn. Độ phân giải của CWG 1630 làm cho khởi tạo mặc định được định dạng tốt bất kể hàm tạo mặc định được chọn là explicit hay không.


Trong biến thể của mã của bạn trong đó iprivate, A không phải là một tổng hợp, vì đây không thể có các thành viên tư nhân. Miễn là ipublic, tuy nhiên, A là tổng hợp và không có hàm tạo nào được gọi kể từ khi khởi tạo tổng hợp (xem hộp màu xanh), vì vậy hàm tạo của bạn là explicit không liên quan.

enter image description here

Tuy nhiên, ngay sau khi bạn giới thiệu thành viên tư nhân, bạn đòi hỏi giá trị khởi tạo theo các hộp màu đỏ. Do đó [dcl.init]/(8.2) được áp dụng:

[dcl.init]/(7.1) định nghĩa mặc định-khởi cho trường hợp này:

enter image description here

Và §13.3 .1.3 cung cấp cho

For […] default-initialization, the candidate functions are all the constructors of the class of the object being initialized.

Không có điểm nào là bối cảnh gốc - sao chép hoặc khởi tạo trực tiếp - được xem xét. (§13.3.1.7 cũng không áp dụng.) Trên thực tế, điều này được dự định; thấy CWG #1518:

This issue is resolved by the resolution of issue 1630 : default initialization now uses 13.3.1.3 [over.match.ctor], which now permits explicit constructors for default-initialization.

Clang và GCC (và VC++) đã không được thực hiện các DR tương ứng được nêu ra và do đó không chính xác trong việc từ chối mã trong chế độ 14 C++.


1) lớp của bạn có một constructor do người dùng khai báo, nhưng nó không phải là do người sử dụng cung cấp , ví dụ: không cản trở lớp học của bạn từ trở thành một tổng thể. Nhớ lại định nghĩa trong [dcl.init.aggr]/1:

An aggregate is an array or a class (Clause 9) with no user-provided constructors (12.1), no private or protected non-static data members (Clause 11), no base classes (Clause 10), and no virtual functions (10.3).

+2

Không phải [CWG 1518] (http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1518) có liên quan đến trường hợp này không? – bogdan

+0

@bogdan Đợi đã, kết luận ban đầu của tôi có đúng không? – Columbo

+0

Tôi muốn nói như vậy, nhưng tôi không chắc chắn 100% bản thân mình :-). – bogdan

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