Hãy xem xét ví dụ sau ( đoạn trích (0) ):
struct X
{
constexpr int get() const { return 0; }
};
void foo(const X& x)
{
constexpr int i = x.get();
}
int main()
{
foo(X{});
}
Ví dụ trên biên dịch với tất cả các phiên bản g++
trước g++ 10.x
và không bao giờ được biên dịch theo clang++
. Thông báo lỗi là:
error: 'x' is not a constant expression 8 | constexpr int i = x.get(); |
ví dụ trực tiếp trên godbolt.org
Tuy nhiên, loại lỗi có ý nghĩa, x
không bao giờ là một biểu thức không đổi trong cơ thể của foo
:
X::get()
được đánh dấuconstexpr
và nó không phụ thuộc vào trạng thái củax
;Thay đổi
const X&
đểconst X
làm cho mã được biên dịch với mọi trình biên dịch (trên godbolt.org) đoạn trích (1) .
Nó thậm chí còn thú vị hơn khi tôi đánh dấu X::get()
là static
( (trên godbolt.org) đoạn trích (2) ). Với sự thay đổi đó, tất cả các phiên bản đã thử nghiệm của g++
(bao gồm cả thân cây) biên dịch, trong khi clang++
vẫn luôn không biên dịch được.
Vì vậy, câu hỏi của tôi:
Có
g++ 9.x
đúng trong việc chấp nhận đoạn trích (0) không?Có phải tất cả các trình biên dịch đều đúng trong việc chấp nhận đoạn trích (1) không? Nếu vậy, tại sao các tài liệu tham khảo có ý nghĩa?
Là
g++ 9.x
vàg++ trunk
chính xác trong việc chấp nhận đoạn trích (2) ?
x
trong foo
không phải là một biểu thức hằng. Thậm chí còn có một báo cáo lỗi cũ (bị từ chối không chính thức) về tiếng kêu cho hành vi đúng của nó (trong khi GCC có một lỗi thực sự cho nó).