2015-12-21 15 views
15

Đoạn đầu tiên biên dịch mà không cần bất kỳ cảnh báo (live example):Tại sao các đoạn mã này được GCC xử lý khác nhau?

#include <iostream> 

struct A { 
    constexpr A(): i(5){} 
    constexpr operator int() { return 5; } 
    int i; 
}; 

int main() { 
    A a; 
    int b[a]{ 0, 1, 2, 3, 4 }; 
    std::cout << b[4] << '\n'; 
} 

Bây giờ thay đổi đoạn trên bằng cách quay i trong các nhà điều hành chuyển đổi (live example):

constexpr operator int() { return i; } 

GCC cảnh báo rằng b là một VLA .

Với tôi, cả hai biến thể có vẻ phù hợp với đoạn §5.19 [expr.const]/3 trong C++ 14.

Trả lời

17

Bạn đang thực hiện một chuyển đổi lít trên i, nhưng đối với [expr.const]/(2.7) không được vi phạm ở đây, (2.7.3) phải được áp dụng:

enter image description here

(2.7.1) liên quan đến các đối tượng hoàn chỉnh, (2.7.2) nói về các chuỗi ký tự và (2.7.4) là về các đối tượng có tuổi thọ bắt đầu trong quá trình đánh giá biểu thức - không áp dụng được vì tờ khai của a đứng trước số b.

Xác định aconstexpr và mã tuân thủ.


Một phụ lục ít để làm rõ những gì tiêu chuẩn nói: Biểu thức bên trong dấu ngoặc phải là một biểu hiện thường xuyên chuyển đổi loại std::size_t ([dcl.array]/1), được định nghĩa trong [expr.const]/4 như

Một chuyển đổi biểu thức liên tục của loạiT là một biểu thức, được chuyển đổi hoàn toàn thành loại T, trong đó biểu thức được chuyển đổi là biểu thức không đổi và [… yêu cầu được đáp ứng…]

Như vậy, thực sự, tiêu chuẩn quan tâm đến việc có hay không

constexpr std::size_t s = a; 

sẽ là hợp lệ. Mà nó không phải là, cho những lý do nói trên - cố gắng sử dụng một subobject của một đối tượng được xác định trước, không constexpr.

+0

Tại sao 'a' phải trải qua một chuyển đổi từ rvalue sang rvalue trong trường hợp này? Tôi hỏi điều này, bởi vì định nghĩa của một 'biểu thức hằng số được chuyển đổi' trong §5.19/3 (N4140) dường như không đòi hỏi sự chuyển đổi từ' a' trong khai báo 'int b [a] {0, 1 , 2, 3, 4}; '. – Ayrosa

+0

@Ayrosa Vâng, 'a' không bao giờ phải trải qua một, nhưng toán tử chuyển đổi của nó phải được gọi để chuyển nó thành' std :: size_t'. ('a' là một biểu thức hằng số được chuyển đổi kiểu' std :: size_t' bên trong dấu ngoặc đơn) – Columbo

+1

Tôi mất một lúc để nắm bắt những gì bạn nói và đánh dấu trong câu trả lời của bạn.Chắc chắn, nó không phải là một nhiệm vụ dễ dàng cho một, để hiểu đầy đủ các tiêu chuẩn. Câu trả lời hay (+1). – Ayrosa

4

Kích thước mảng phải là hằng số thời gian biên dịch, nhưng trong ví dụ thứ hai, việc khởi tạo A::i không xảy ra cho đến thời gian chạy.

+0

'A :: A()' là 'constexpr' mặc dù ... – YSC

+0

@YSC Có, nhưng biến' a' trong hàm 'main' thì không. –

+1

Và * đây * là nguồn cảnh báo thực sự, phải không? – YSC

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