2017-12-20 99 views
7

Là một followup để this question, gcc và Clang cả xem xét chương trình này vô hình thành:khởi tham khảo và các biểu thức liên tục

int main() { 
    const int& ri = 0; 
    constexpr int i = ri; 
} 

Lỗi này là về giá trị của ri là không sử dụng được trong một biểu thức hằng. 0 chắc chắn là một biểu thức liên tục cốt lõi, và như là một biểu thức hằng số lõi prvalue dường như đáp ứng these constraints (tầm thường, vì int không phải là loại lớp, con trỏ hoặc mảng). Vì vậy, không nên ri đáp ứng this criteria?

Điều này cũng đúng nếu tôi sử dụng một prvalue đen của kiểu lớp:

struct X { }; 
int main() { 
    const X& rx = X{}; 
    constexpr X x = rx; 
} 
+0

Một đối tượng không thể là lớp, con trỏ và loại mảng cùng một lúc. Không có đối tượng nào có thể đáp ứng tất cả các ràng buộc. Nó phải thỏa mãn cái thích hợp. Một đối tượng kiểu 'int' thỏa mãn cả hai. Vì vậy, không, 'ri' sẽ không áp dụng. – StoryTeller

+0

D'oh. Cảm ơn bạn đã làm cho tôi biết rằng tôi đã hiểu sai [\ [expr.const \]/6] (http://eel.is/c++draft/expr.const#6.sentence-2). Nó nên đọc "đối tượng có thời gian lưu trữ tĩnh (hoặc không phải là đối tượng tạm thời hoặc là đối tượng tạm thời có giá trị thỏa mãn các ràng buộc trên)", không phải "(đối tượng có thời lượng lưu trữ tĩnh không phải là đối tượng tạm thời) hoặc (là một đối tượng tạm thời có giá trị thỏa mãn các ràng buộc trên) "#:. – cpplearner

+0

@StoryTeller Ràng buộc 'P -> Q' được thỏa mãn bởi'! P'. – Barry

Trả lời

1

Như bạn chỉ ra, 2.11 bang rằng một lõi liên tục biểu phải không đánh giá để:

  • biểu thức id đề cập đến biến hoặc thành viên dữ liệu của loại tham chiếu trừ khi tham chiếu có khởi tạo trước và hoặc

    • nó được khởi tạo với một biểu thức hằng hoặc

Và hơn nữa expr.const # 6:

Một biểu thức hằng số hoặc là một lõi glvalue liên tục biểu đề cập đến một thực thể là kết quả được phép của một biểu thức hằng số (như được định nghĩa bên dưới), hoặc một hằng số nguyên tố prvalue ex pression có giá trị đáp ứng các hạn chế sau:

...

Một thực thể là kết quả phép của một biểu thức hằng số nếu nó là một đối tượng với thời gian lưu trữ tĩnh đó là một trong hai không phải là một đối tượng tạm thời hoặc là một đối tượng tạm thời có giá trị thỏa mãn các ràng buộc ở trên hoặc đó là một hàm.

Từ đọc sách của tôi điều này, nó có nghĩa là RHS của const X& r = (thay thế X đối với một số loại) phải là đối tượng có thời gian lưu trữ tĩnh hay một đối tượng tạm thời đáp ứng các tiêu chí trên. Vì int không phù hợp với đối tượng thuộc loại lớp, kiểu con trỏ hoặc loại lớp/mảng, nó không đủ điều kiện.

5

Trong tuyên bố này:

const int& ri = 0; 

0 là một prvalue, nhưng ri không được khởi tạo từ prvalue đó. Giá trị đầu tiên trải qua một số temporary materialization conversion và tham chiếu bị ràng buộc với glvalue kết quả.Vì ri bị ràng buộc bởi glvalue vật chất hóa này, và không trực tiếp đến giá trị như bạn (I), các hạn chế có liên quan không phải là giới hạn biểu thức hằng số lõi (mà 0 thỏa mãn), thay vào đó là giới hạn biểu thức liên tục của glvalue. thực thể là permitted result of a constant expression. hạn chế đó, đánh vần với cải thiện đôi chút trong trẻo, là:

hoặc một đối tượng với thời gian lưu trữ tĩnh đó là:

  • không phải là một đối tượng tạm thời, hoặc
  • một đối tượng tạm thời có giá trị đáp ứng trên ràng buộc,

hoặc là hàm.

glvalue chúng tôi một đối tượng tạm thời có giá trị thỏa mãn "những hạn chế nêu trên" ("trên" ở đây đề cập đến những hạn chế liên tục prvalue lõi, mà int trivially đáp ứng), nhưng nó không có lưu trữ tĩnh thời gian.

Không có thời gian lưu trữ tĩnh → thực thể không phải là một kết quả phép của một biểu thức hằng → khái niệm glvalue không phải là một biểu thức hằng → ri không được khởi tạo với một biểu thức hằng → ri không thể được sử dụng trong một hằng số lõi biểu thức → tuyên bố của i là không đúng định dạng.

Đối số tương tự cũng giữ cho các loại lớp thích hợp.

+1

Thời gian lưu trữ tĩnh có nghĩa là gì? –

+0

@PasserBy Đó là một câu hỏi hay. – Barry

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