Vào ngày 15 tháng 7 năm 17, P0329R4 đã được chấp nhận vàoc ++ 20standard: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0329r4.pdf
Điều này mang lại hỗ trợ hạn chế choc99Bộ khởi tạo được chỉ định. Hạn chế này được mô tả như sau trong C.1.7 [diff.decl] .4, đưa ra:
struct A { int x, y; };
struct B { struct A a; };
Các khởi tạo được chỉ định sau đây, hợp lệ trong C, bị hạn chế trong C ++:
struct A a = { .y = 1, .x = 2 }
không hợp lệ trong C ++ vì người chỉ định phải xuất hiện trong thứ tự khai báo của các thành viên dữ liệu
int arr[3] = { [1] = 5 }
không hợp lệ trong C ++ vì không hỗ trợ khởi tạo mảng được chỉ định
struct B b = {.a.x = 0}
không hợp lệ trong C ++ vì không thể lồng ghép các ký hiệu chỉ định
struct A c = {.x = 1, 2}
không hợp lệ trong C ++ vì tất cả hoặc không có thành viên dữ liệu nào phải được khởi tạo bởi người chỉ định
Đối với c ++ 17và Boost trước đó thực sự có hỗ trợ cho Intializers được chỉ định và đã có nhiều đề xuất để thêm hỗ trợ choc ++tiêu chuẩn, ví dụ: n4172 và Đề xuất của Daryle Walker để Thêm Chỉ định vào Bộ khởi tạo . Các đề xuất trích dẫn việc thực hiệnc99Các trình khởi tạo được chỉ định của Visual C ++, gcc và Clang tuyên bố:
Chúng tôi tin rằng những thay đổi sẽ tương đối dễ thực hiện
Nhưng ủy ban tiêu chuẩn liên tục từ chối các đề xuất như vậy , nói rõ:
EWG đã tìm thấy nhiều vấn đề khác nhau với cách tiếp cận được đề xuất và không nghĩ rằng việc thử giải quyết vấn đề này là khả thi, vì nó đã được thử nhiều lần và lần nào cũng thất bại
Những nhận xét của Ben Voigt đã giúp tôi thấy được những vấn đề không thể vượt qua với cách tiếp cận này; được:
struct X {
int c;
char a;
float b;
};
Thứ tự các hàm này sẽ được gọi trong c99: struct X foo = {.a = (char)f(), .b = g(), .c = h()}
? Đáng ngạc nhiên, trongc99:
Thứ tự đánh giá các biểu thức phụ trong bất kỳ trình khởi tạo nào được sắp xếp theo trình tự không xác định [ 1 ]
(Visual C ++, gcc và Clang dường như có một hành vi đã được thỏa thuận vì tất cả chúng sẽ thực hiện các lệnh gọi theo thứ tự này :)
h()
f()
g()
Nhưng bản chất không xác định của tiêu chuẩn có nghĩa là nếu các chức năng này có bất kỳ tương tác nào, trạng thái chương trình kết quả cũng sẽ không xác định và trình biên dịch sẽ không cảnh báo bạn : Có Cách nào để Cảnh báo về việc Hoạt động sai Bộ khởi tạo được Chỉ định không?
c ++ không có yêu cầu nghiêm ngặt initializer-list 11.6.4 [dcl.init.list] 4:
Trong danh sách bộ khởi tạo của một danh sách giằng-init, các mệnh đề bộ khởi tạo, bao gồm bất kỳ điều khoản nào là kết quả của việc mở rộng gói (17.5.3), được đánh giá theo thứ tự mà chúng xuất hiện. Có nghĩa là, mọi phép tính giá trị và phụ liên kết với một mệnh đề khởi tạo nhất định được giải trình tự trước mọi phép tính giá trị và tác dụng phụ được liên kết với bất kỳ mệnh đề khởi tạo nào theo sau nó trong danh sách được phân tách bằng dấu phẩy của danh sách bộ khởi tạo.
Vì thế c ++ hỗ trợ sẽ yêu cầu điều này được thực hiện theo thứ tự:
f()
g()
h()
Phá vỡ khả năng tương thích với trước đó c99triển khai.
Như đã thảo luận ở trên, vấn đề này đã được giải quyết bởi những hạn chế về Trình khởi tạo được chỉ định được chấp nhận vàoc ++ 20. Chúng cung cấp một hành vi tiêu chuẩn hóa, đảm bảo thứ tự thực thi của các Trình khởi tạo được Chỉ định.