2016-09-22 29 views
9

Theo như tôi thấy, một tình huống rất phổ biến là một cái gì đó giống nhưconstexpr thành viên tĩnh trước/sau C++ 17

template<int i> class Class 
{ 
public: 
    static constexpr int I = i; 
    static constexpr int J = constexprFunction(i); 
    // further Class implementation 
}; 

Hầu như chung tôi thấy sai lầm (trong thực tế hầu hết các câu hỏi của tôi ở đây là vì tôi quên nó và không biết, những gì các câu hỏi thích hợp đã được) để quên đi những nét bổ sung nếu các thành viên ODR-sử dụng:

template<int i> constexpr int Class<i>::I; 
template<int i> constexpr int Class<i>::J; 

Bây giờ tôi đọc cppreference: Definitions and ODRcppreference: static members, mà nhà nước, điều này bị phản đối cho C++ 17. Điều này có vẻ tuyệt vời với tôi, bởi vì nó tránh được rất nhiều lỗi. Nhưng có những câu hỏi khác, xuất hiện:

1) Thay đổi này có lý do khác hơn là làm cho các định nghĩa bổ sung vô dụng không? (Xem thêm đoạn cuối của câu hỏi này)

2) Trong ví dụ cuối cùng của cppreference: static members, có vẻ như cũng áp dụng cho thành viên const static - nhưng quy tắc chỉ nêu thành viên constexpr. Nó sẽ áp dụng trên const static thành viên hay không?

3) Tất cả các ví dụ tôi tìm thấy đều sử dụng một định nghĩa đơn giản như Class::I - tất cả đều giữ trạng thái tại Class:J với chức năng constexpr không?

Trạng thái ngắn gọn những gì thực tiễn tốt nhất là trước C++ 17 và với C++ 17 sẽ tuyệt vời. Tất cả trong tất cả điều này dường như là một sự thay đổi rất khó khăn đối với tôi, bởi vì nó sẽ tạo ra rất nhiều mã, đó là "không được chẩn đoán hình thành không đúng" trước đây, với mã tốt (theo như tôi hiểu ...). Và do đó sẽ có mã được sản xuất, đó vẫn là "hình thành không chẩn đoán không cần thiết" với trình biên dịch cũ (trước 17) - nhưng chúng sẽ không phàn nàn, miễn là không cần sử dụng odr.

Chỉnh sửa: Sửa văn bản, được đề xuất bởi Aaron McDaid.

+2

Tôi nghĩ ví dụ cuối cùng về các thành viên dữ liệu tĩnh là lỗi chỉnh sửa (hiện đã được sửa): 9.2.3.2 [class.static.data] p3 cho biết, đối với "thành viên dữ liệu tĩnh không cố định không cố định", " thành viên vẫn sẽ được xác định trong một phạm vi không gian tên nếu nó được sử dụng không đúng " – Cubbi

+1

Tôi đang bối rối bởi văn bản trong câu hỏi hiện tại: *" nhầm lẫn ... để đưa ra định nghĩa nếu các thành viên được sử dụng odr "*. Chắc chắn bạn có nghĩa là, trong C + + 11 ví dụ, rằng nó là một sai lầm để * thất bại * để đưa ra một định nghĩa? Bạn đã quên một sự phủ nhận? (Xin lỗi nếu điều này có vẻ rất đơn giản, nhưng tôi thực sự không biết điều này cũng đủ để chắc chắn về ý định ở đây) –

+0

@AaronMcDaid Có, điều đó là đúng sự thật. Tôi sửa nó rồi. Tôi rõ ràng có nghĩa là nó là cần thiết để cung cấp cho các định nghĩa bổ sung trong C + + 11, nhưng điều này không còn đúng trong C++ 17. Do đó tôi đã cố gắng giải thích sự nhầm lẫn của mình với mục đích tương thích xuống trong đoạn cuối. – marlam

Trả lời

5

Thay đổi này là do đề xuất biến nội tuyến (P0386). static constexpr sẽ ngụ ý inline, làm cho các định nghĩa thừa.

Trong Phụ lục D, thêm một phân lớp mới, “khai báo lại các thành viên dữ liệu constexpr tĩnh”, DX, với các nội dung sau đây: Để tương thích với tiêu chuẩn quốc tế trước khi C++, một thành viên constexpr dữ liệu tĩnh có thể được dư thừa redeclared ngoài lớp không có bộ khởi tạo. Việc sử dụng này không được chấp nhận.

[Ví dụ:

struct A { 
static constexpr int n = 5; // definition (declaration in C++2014) 
}; 
const int A::n; // redundant declaration (definition in C++2014) 

-end dụ]

Về câu hỏi của bạn:

Có sự thay đổi này lý do khác hơn làm cho các định nghĩa thêm vô dụng?

Thực chất là không. Tuy nhiên, nó có sử dụng bổ sung bên cạnh một trong những bạn ghi nhận (xem này question). Đề xuất này đã gây tranh cãi vì nó có thể khuyến khích việc sử dụng một trạng thái toàn cầu có thể thay đổi được.

Nó có áp dụng cho const static thành viên hay không?

No. Trừ khi bạn chú thích nó là inline.

hiện tại tất cả cũng giữ cho tình huống tại Class:J với chức năng constexpr?

Có. Đề xuất đề cập đến liên kết nhưng không ảnh hưởng đến các quy tắc khởi tạo.

+0

Tôi biết đó là một câu trích dẫn, nhưng không phải là một chút bối rối khi khai báo một 'constexpr' và để định nghĩa nó là' const'? Bởi vì điều này có vẻ như tôi không giống nhau ... – marlam

+0

@marlam Nó làm tôi ngạc nhiên. Tôi nghĩ đó là lỗi đánh máy. – metalfox

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