2015-02-01 30 views
8

Mã này hoạt động:tài liệu tham khảo không xác định khi truy cập thành viên float constexpr tĩnh

struct Blob { 
    static constexpr int a = 10; 
}; 

int main() { 
    Blob b; 
    auto c = b.a; 
} 

Nhưng nếu tôi thay đổi int để float tôi nhận được một lỗi:

struct Blob { 
    static constexpr float a = 10.0f; 
}; 

/tmp/main-272d80.o: In function main': main.cpp:(.text+0xe): undefined reference to Blob::a'

Tại sao tôi không thể sử dụng a constexpr float theo cách đó?

Compiler: Ubuntu kêu vang phiên bản 3.5.0-4ubuntu2 (tags/RELEASE_350/thức)

Thử nghiệm trên phiên bản gcc 4.9.1 (Ubuntu 4.9.1-16ubuntu6) và không có lỗi.

EDIT:

Nó sẽ biên dịch nếu tôi sử dụng -O1, -O2, O3 hoặc -os nhưng không thành công với -O0

+0

Trình biên dịch nào? – P0W

+0

Phiên bản Ubuntu clang 3.5.0-4ubuntu2 (thẻ/RELEASE_350/final) –

+0

@Deduplicator 'error: thành phần dữ liệu không tĩnh không thể là constexpr; bạn có dự định làm cho nó tĩnh? ' –

Trả lời

6

C++ 11 lần đọc

A variable whose name appears as a potentially-evaluated expression is odr-usedunless it is an object that satisfies the requirements for appearing in a constant expression (5.19) and the lvalue-to-rvalue conversion (4.1) is immediately applied.

Rõ ràng chuyển đổi ltr được áp dụng ngay lập tức và biến số constexpr của loại dấu phẩy động có thể xuất hiện trong biểu thức không đổi theo [expr.const]/(2.7.1):

A conditional-expression is a core constant expression unless it involves one of the following as a potentially evaluated subexpression [..]

  • an lvalue-to-rvalue conversion (4.1) unless it is applied to
    • a glvalue of literal type that refers to a non-volatile object defined with constexpr, or that refers to a sub-object of such an object, or

Có vẻ là lỗi Clang.

3

Điều thú vị là, nếu chúng ta sử dụng Blob::a thay vào đó, clang không phàn nàn:

auto c = Blob::a; 

này không nên quan trọng để xác định nếu nó là ODR được sử dụng hay không. Vì vậy, điều này trông giống như một lỗi clang mà tôi có thể tái sản xuất trên clang 3.7 không chỉ sử dụng tối ưu hóa. Chúng ta có thể nói đây là một vấn đề ODR kể từ khi thêm một ra khỏi định nghĩa lớp sửa chữa các vấn đề (see it live):

constexpr float Blob::a ; 

Vì vậy, khi làm bạn cần phải xác định một thành viên lớp constexpr tĩnh? Này được đề cập trong phần 9.4.2[class.static.data] mà nói (tôi nhấn mạnh đi về phía trước):

A static data member of literal type can be declared in the class definition with the constexpr specifier; if so, its declaration shall specify a brace-or-equal-initializer in which every initializer-clause that is an assignment-expression is a constant expression. [ Note: In both these cases, the member may appear in constant expressions. —end note ] The member shall still be defined in a namespace scope if it is odr-used (3.2) in the program and the namespace scope definition shall not contain an initializer.

Nó đòi hỏi một định nghĩa nếu nó được ODR-sử dụng. Nó có được sử dụng không? Không có nó không phải là. Bản gốc C++ 11 từ ngữ trong phần 3.2[basic.def.odr] nói:

An expression is potentially evaluated unless it is an unevaluated operand (Clause 5) or a subexpression thereof. A variable whose name appears as a potentially-evaluated expression is odr-used unless it is an object that satisfies the requirements for appearing in a constant expression (5.19) and the lvalue-to-rvalue conversion (4.1) is immediately applied.

a đáp ứng cả hai điều kiện, đó là một biểu hiện liên tục và chuyển đổi giá trị trái-to-rvalue ngay lập tức được áp dụng.Defect Report 712 đã thay đổi từ ngữ áp dụng cho C++ 11 vì nó là một báo cáo lỗi và 3.2 nay nói:

A variable x whose name appears as a potentially-evaluated expression ex is odr-used unless applying the lvalue-to-rvalue conversion (4.1) to x yields a constant expression (5.19) that does not invoke any non-trivial functions and, if x is an object, ex is an element of the set of potential results of an expression e, where either the lvalue-to-rvalue conversion (4.1) is applied to e, or e is a discarded-value expression

Kết quả tiềm năng phù hợp sẽ là:

If e is an id-expression (5.1.1), the set contains only e.

nó là một biểu hiện thường xuyên và chuyển đổi lvalue-to-rvalue được áp dụng để nó không được sử dụng odr.

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