2013-12-18 19 views
5

Tôi tình cờ gặp mã mà tôi không hiểu. Đây là phiên bản được đơn giản hóa của nó:C++ 98 dấu ngoặc ôm const khởi tạo vô hướng

template <int> struct A {}; 

int const i = { 42 }; 
typedef A<i> Ai; 

int const j = 42; 
typedef A<j> Aj; 

Mã này biên dịch với chế độ GCC ở chế độ C++ 98, chứ không phải trong Clang. Clang tạo ra lỗi sau:

$ clang -Wall -Wextra -std=c++98 -c test.cpp 

test.cpp:4:11: error: non-type template argument of type 'int' is not an integral constant expression 
typedef A<i> Ai; 
     ^
test.cpp:4:11: note: initializer of 'i' is not a constant expression 
test.cpp:3:11: note: declared here 
int const i = { 42 }; 
     ^

Theo tôi hiểu việc khởi tạo int có và không có dấu ngoặc nhọn phải tương đương. Clang khởi tạo i chính xác đến 42, chỉ không nghĩ đó là hằng số thời gian biên dịch.

Mã này biên dịch tốt ở chế độ C++ 11.

Có lý do nào j được coi là hằng số thời gian biên dịch và i không? Hay đơn giản là một con bọ ở Clang?

Cập nhật: Tôi đã mở ticket trong trình theo dõi lỗi LLVM với sự cố này.

+0

tôi sẽ nói đó là một lỗi trong trình biên dịch. – Raxvan

+2

@Raxvan: Đó là một tuyên bố khá táo bạo ... Xem xét nó hoạt động trong C++ 11 và không có trong C++ 98 nó có vẻ khá thận trọng, vì vậy tôi thực sự mong đợi nó sẽ * theo thông số kỹ thuật * (trên phần Clang) và gcc trở nên khoan dung hơn bình thường. –

+0

@MatthieuM .: Tôi nghĩ rằng đây là những gì anh ấy muốn nói: một lỗi trong gcc. Không có cú pháp C++ 98 cho điều này, và clang rightfully từ chối nó. Vì vậy, chấp nhận nó trong gcc, mặc dù không phải là C++ 98, là một lỗi. – PlasmaHH

Trả lời

2

Các lỗi biên dịch nói rằng "template argument of type 'int' is not an integral constant expression" cho int const i = { 42 };

Theo 98 standard đối số mẫu nên rơi vào thể loại này:

14.3.2/1

A template-argument for a non-type, non-template template-parameter shall be one of:

  • an integral constant-expression of integral or enumeration type; or

...

và định nghĩa của biểu thức hằng số tách rời int const i fa sẽ vào thể loại này:

5.19 Constant expressions

An integral constant-expression can involve only literals (2.13), enumerators, const variables or static data members

và cho khởi của i (như Mike Seymour bưu điện):

8.5 Initializers /13

If T is a scalar type, then a declaration of the form

T x = { a };

is equivalent to

T x = a;

Bây giờ dựa trên this post tuyên bố const intint const nên giống nhau (không thể tìm thấy điều này đặc biệt trong tiêu chuẩn) làm cho i a biến const. Vì vậy, bất kỳ cách sử dụng nào của i phải là một biểu thức hằng số không tách rời bất kể phương thức khởi tạo. Nó xuất hiện có một lỗi trong clang.Kiểm tra các trang web tôi không thể tìm thấy một báo cáo lỗi chỉ có hai ít nhiều tương tự:

http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=666539

http://lists.cs.uiuc.edu/pipermail/llvmbugs/2011-March/017353.html

5

Vâng, cả hai tờ khai là tương đương, mỗi C++ 98 8.5/13:

If T is a scalar type, then a declaration of the form

T x = { a }; 

is equivalent to

T x = a; 

Vì vậy, cả hai biến là hằng số, và được khởi tạo từ một biểu thức hằng, vì vậy (theo như tôi có thể thấy) cả hai có thể sử dụng được như là các biểu thức không đổi.

1

Tôi nghĩ rằng Clang là đúng. danh sách khởi tạo không phải là một biểu thức. Có sự khác biệt giữa việc khởi tạo các đối tượng tổng hợp và các đối tượng cơ bản. Khi một đối tượng POD được khởi tạo thì mỗi bộ khởi tạo có thể được coi là biểu thức const. Tuy nhiên khi bạn đối phó với các kiểu cơ bản thì danh sách khởi tạo không phải là một biểu thức và không phải là một biểu thức const.

Trong đoạn # 14 của tiêu chuẩn có chép rằng:

The source type is not defined when the initializer is brace-enclosed or when it is a parenthesized list of expressions

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