2015-03-26 21 views
7

Các mã sau biên dịch và chạy trong gcc 4.9.1 và Clang-3.6 khi sử dụng -std = C++ 11:khởi của mảng thành viên constexpr tĩnh trong gcc 4.8

struct Bar 
{ 
    int x; 
}; 

struct Foo 
{ 
    static constexpr Bar bars[] = {1, 2, 3}; 
}; 

constexpr Bar Foo::bars[]; 

Tuy nhiên, nó không thành công trong gcc 4.8.3, kết quả được thông báo lỗi

./cpptest.cpp:14:43: error: could not convert '1' from 'int' to 'const Bar' 
    static constexpr Bar bars[] = {1, 2, 3}; 
             ^
./cpptest.cpp:14:43: error: could not convert '2' from 'int' to 'const Bar' 
./cpptest.cpp:14:43: error: could not convert '3' from 'int' to 'const Bar' 

Ngẫu nhiên, nếu tôi làm điều tương tự nhưng làm bars một mảng toàn cầu const tĩnh, nó biên dịch tốt trong gcc 4.8 và kêu vang. Nó cũng sẽ biên dịch tốt nếu tôi bao quanh từng chữ số nguyên trong danh sách với một cặp phụ là {}.

Vì vậy, đây có phải là lỗi trong gcc 4.8 không? Tiêu chuẩn nói gì là cú pháp thích hợp cho điều này? Phần nào của tiêu chuẩn khởi tạo đồng nhất C++ 11 đang được gọi khi tôi bỏ qua các dấu ngoặc phụ thừa?

Chỉnh sửa: Có vẻ như tiêu chuẩn nói rằng điều này nên gọi khởi tạo tổng hợp, cho phép "giải phóng cú đúp". Vì vậy, có vẻ như đó là lỗi trong gcc 4.8, được sửa bởi gcc 4.9, nhưng tôi hoàn toàn không tự tin khi đọc tiêu chuẩn. Tôi cũng không thể tìm thấy bất kỳ báo cáo lỗi nào trong trình theo dõi lỗi của gcc về vấn đề này, vì vậy tôi có thể dễ dàng bị sai.

+0

Bạn có cho rằng đó là lỗi đã được khắc phục không? – edmz

Trả lời

2

Để làm những gì bạn muốn làm, bạn cần chỉ định một constructor constexpr bên Foo:

struct Bar 
{ 
    constexpr Bar(int c) : x(c) 
    {} 

    int x; 
}; 

struct Foo 
{ 
    static constexpr Bar bars[] = {1, 2, 3}; 
}; 

constexpr Bar Foo::bars[]; 

4.8.3 Rõ ràng gcc không implicity chuyển đổi các giá trị bên trong dấu ngoặc nhọn Bar đối tượng, trong khi gcc 4.9.1.

+0

Chắc chắn rồi, và đó là con đường mà tôi đã kết thúc. Điều này đã kết thúc lộ một lỗi khác trong gcc 4.9 (mà tôi đã báo cáo ở đây: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65695). Nhưng câu hỏi của tôi là, nên tiêu chuẩn cho phép khởi tạo mà không có những niềng răng? Và tôi nghĩ rằng câu trả lời là có, nó chỉ đơn giản là một lỗi trong xử lý gcc của brace elision với các thành viên constexpr. –

+0

Tôi sẽ không gọi đây là lỗi. GCC chỉ đơn giản là yêu cầu từ bạn khai báo một hàm tạo constexpr khi bạn khai báo một biến constexpr. Tôi cũng nhìn vào báo cáo lỗi của bạn và trả lời nó. Những gì bạn muốn làm ở đó không nên làm việc: Bạn không nên lưu trữ địa chỉ của một hàm thành viên không tĩnh trong một biến tĩnh. – kamshi

+0

GCC 4.8 tuyên bố để hỗ trợ tiêu chuẩn ISO/IEC 14882: 2011 (C++ 11). Nếu sự thất bại trong việc cho phép giải phẫu brace vi phạm tiêu chuẩn (và tôi khá chắc chắn nó), thì đó là một lỗi trong GCC 4.8. Và, tương tự, tiêu chuẩn có một phần về biểu thức không đổi. Nó đưa ra một danh sách dài những thứ không phải là biểu thức liên tục. Dựa trên đọc của tôi (thừa nhận nghiệp dư) của tiêu chuẩn, địa chỉ của một hàm thành viên không tĩnh là một biểu thức liên tục. –

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