Cú pháp hợp lệ của việc gọi hàm hủy giả cho hằng số trôi nổi


9

Hãy xem xét các chương trình trình diễn sau đây.

#include <iostream>

int main()
{
    typedef float T;

    0.f.T::~T();
}

Chương trình này được biên soạn bởi Microsoft Visual Studio Community 2019.

Nhưng clanggccđưa ra một lỗi như thế này

prog.cc:7:5: error: unable to find numeric literal operator 'operator""f.T'
    7 |     0.f.T::~T();
      |     ^~~~~

Nếu để viết biểu thức như thế ( 0.f ).T::~T()thì cả ba trình biên dịch biên dịch chương trình.

Vì vậy, một câu hỏi đặt ra: hồ sơ này 0.f.T::~T()có hợp lệ về mặt cú pháp không? Và nếu không, thì quy tắc cú pháp nào bị phá vỡ?


1
Đặt một khoảng trống giữa 0.f.Tkhiến cả GCC và Clang chấp nhận điều này ...
chris

1
Cũng như(0.f).T::~T();
cigien

Một đơn giản float f = 1.0f.t;sẽ tạo ra lỗi về chữ số.
1201ProgramAlarm

Một floatlà một built-in loại, nó không có một destructor để bạn có thể gọi. Bạn thậm chí đang làm gì bằng cách gọi thủ công hủy diệt? Bên ngoài lãnh thổ vị trí mới, đó sẽ là một điều không nên lớn .
Jesper Juhl

@JesparJuhl nó không phải là kẻ hủy diệt mà là kẻ hủy diệt giả, tôi chỉ cần biết rằng nó tồn tại. Thông tin thẻ có một ví dụ (cũng có một cuộc gọi không chính đáng đến hàm hủy btw)
idclev 463035818

Câu trả lời:


3

Việc phân tích cú pháp mã số khá thô và cho phép nhiều thứ không thực sự là số hợp lệ. Trong C ++ 98, ngữ pháp cho "số tiền xử lý", được tìm thấy trong [lex.ppnumber], là

pp-number:
    digit
    . digit
    pp-number digit
    pp-number nondigit
    pp-number e sign
    pp-number E sign
    pp-number .

Ở đây, "số không" là bất kỳ ký tự nào có thể được sử dụng trong mã định danh, ngoài các chữ số và "ký hiệu" là + hoặc -. Các tiêu chuẩn sau này sẽ mở rộng định nghĩa để cho phép các trích dẫn đơn (C ++ 14) và các chuỗi có dạng p-, p +, P-, P + (C ++ 17).

Kết quả cuối cùng là, trong bất kỳ phiên bản nào của tiêu chuẩn, trong khi số tiền xử lý được yêu cầu bắt đầu bằng một chữ số hoặc một khoảng thời gian theo sau một chữ số, sau đó một chuỗi chữ số, chữ cái và dấu chấm tùy ý có thể theo sau. Sử dụng quy tắc munch tối đa, nó tuân theo 0.f.T::~T();yêu cầu phải được mã hóa thành 0.f.T :: ~ T ( ) ;, mặc dù 0.f.Tkhông phải là mã thông báo số hợp lệ.

Do đó, mã không hợp lệ về mặt cú pháp.


Thật thú vị, thực sự có một ví dụ với sự tương đồng khá trong [lex.pptoken]: eel.is/c++draft/lex.pptoken#5
chris

1

Một hậu tố được xác định bởi người dùng, ud-hậu tố , là một định danh . Một định danh là một chuỗi các chữ cái (bao gồm một số ký tự ASCII), gạch dưới, và con số mà không bắt đầu bằng một số. Các nhân vật thời gian không được bao gồm.

Do đó, đây là một lỗi trình biên dịch vì nó đang xử lý chuỗi không định danh f.Tlà định danh.

Đây 0.là một hằng số phân số , có thể được theo sau bởi một số mũ tùy chọn, sau đó là hậu tố ud (đối với một người dùng được xác định bằng chữ) hoặc hậu tố dấu phẩy động (một trong số fFlL). Cũng fcó thể được coi là một ud-achx , nhưng vì nó phù hợp với một loại nghĩa đen khác nên nó không phải là UDL. Một hậu tố ud được định nghĩa trong ngữ pháp như một định danh.


Tại sao nó được hiểu là hậu tố ud?
Vlad từ Moscow

@VladfromMoscow Đây 0.hằng số phân số . Điều đó có thể được theo sau bởi (không bao gồm các số mũ) một hậu tố ud (đối với một người dùng được xác định bằng chữ) hoặc một hậu tố dấu phẩy động (một trong số fFlL). Cũng fcó thể được coi là một ud-achx , nhưng vì nó phù hợp với một loại nghĩa đen khác nên nó không phải là UDL. Một hậu tố ud được định nghĩa trong ngữ pháp như một định danh .
1201ProgramAlarm

@ 1201ProgramAlarm: Trong khi đó fcó thể được hiểu là hậu tố ud, f.Tkhông nên như .không thể có trong định danh. nhưng nó là ... tôi sẽ nói lỗi trình biên dịch nhưng khá chắc chắn rằng nó phức tạp hơn.
Jarod42
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.