ไวยากรณ์ที่ถูกต้องของการเรียกใช้ pseudo-destructor สำหรับค่าคงที่แบบลอยตัว


9

พิจารณาโปรแกรมสาธิตต่อไปนี้

#include <iostream>

int main()
{
    typedef float T;

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

Microsoft Visual Studio Community 2019โปรแกรมนี้เป็นโปรแกรมที่รวบรวมโดย

แต่clangและgccออกข้อผิดพลาดเช่นนี้

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

หากต้องการเขียนนิพจน์เช่น( 0.f ).T::~T()นั้นคอมไพเลอร์ทั้งสามจะคอมไพล์โปรแกรม

ดังนั้นคำถามที่เกิดขึ้น: บันทึกนี้0.f.T::~T()ถูกต้องตามหลักไวยากรณ์หรือไม่ และถ้าไม่เช่นนั้นกฎเกี่ยวกับวากยสัมพันธ์คืออะไร?


1
ใส่ช่องว่างระหว่าง0.fและ.Tเป็นสาเหตุที่ทำให้ทั้ง GCC และเสียงดังกราวจะยอมรับเรื่องนี้ ...
คริส

1
เช่นเดียวกับ(0.f).T::~T();
cigien

วิfloat f = 1.0f.t;จะสร้างข้อผิดพลาดเกี่ยวกับตัวอักษรตัวเลข
1201 โปรแกรม

A floatเป็นชนิดในตัวไม่มีตัวทำลายสำหรับให้คุณโทร คุณกำลังทำอะไรด้วยตนเองที่เรียกว่า destructors? นอกอาณาเขตใหม่ตำแหน่งที่ควรจะเป็นใหญ่ไม่มี
Jesper Juhl

@ JesparJuhl มันไม่ใช่ destructor แต่เป็น destructor หลอกฉันแค่รู้ว่ามันมีอยู่จริง ข้อมูลแท็กมีตัวอย่าง (ซึ่งมีการโทรที่ไม่เป็นธรรมไปยัง destructor btw ด้วย)
idclev 463035818

คำตอบ:


3

การวิเคราะห์โทเค็นเชิงตัวเลขค่อนข้างหยาบและอนุญาตให้มีหลายสิ่งที่ไม่ใช่ตัวเลขที่ถูกต้องจริง ใน C ++ 98 ไวยากรณ์สำหรับ "หมายเลขการประมวลผลล่วงหน้า" ซึ่งพบใน [lex.ppnumber] คือ

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

ที่นี่ "nondigit" เป็นตัวละครใด ๆ ที่สามารถใช้ในตัวระบุนอกเหนือจากตัวเลขและ "เครื่องหมาย" คือ + หรือ - มาตรฐานในภายหลังจะขยายคำจำกัดความเพื่ออนุญาตเครื่องหมายคำพูดเดี่ยว (C ++ 14) และลำดับของรูปแบบ p-, p +, P-, P + (C ++ 17)

ผลที่สุดคือในทุกรุ่นของมาตรฐานในขณะที่หมายเลข preprocessing จะต้องเริ่มต้นด้วยตัวเลขหรือจุดตามด้วยตัวเลขหลังจากนั้นลำดับของตัวเลขตัวอักษรและจุดตามลำดับโดยพลการ การใช้กฎการแทะเล็มสูงสุดกฎต่อไป0.f.T::~T();นี้จำเป็นต้องได้รับโทเค็นเป็น0.f.T :: ~ T ( ) ;แม้ว่า0.f.Tจะไม่ใช่โทเค็นตัวเลขที่ถูกต้อง

ดังนั้นรหัสไม่ถูกต้องทางวากยสัมพันธ์


น่าสนใจจริงๆแล้วมีตัวอย่างที่มีความคล้ายคลึงกันใน [lex.pptoken]: eel.is/c++draft/lex.pptoken#5
chris

1

ผู้ใช้ที่กำหนดไว้ต่อท้ายตัวอักษรUD-ต่อท้ายเป็นตัวระบุ ระบุเป็นลำดับของตัวอักษร (รวมทั้งบางส่วนอักขระที่ไม่ใช่ ASCII) ขีดและตัวเลขที่ไม่ได้เริ่มต้นด้วยจำนวนหนึ่ง อักขระระยะเวลาไม่รวม

ดังนั้นจึงเป็นข้อผิดพลาดคอมไพเลอร์ตามที่มันกำลังรักษาลำดับที่ไม่ใช่ตัวระบุf.Tเป็นตัวระบุ

0.เป็นเศษส่วนอย่างต่อเนื่องซึ่งสามารถตามด้วยสัญลักษณ์ตัวเลือกแล้วทั้งUD-ต่อท้าย (สำหรับผู้ใช้กำหนดตัวอักษร) หรือลอยจุดต่อท้าย (หนึ่งในfFlL ) fสามารถพิจารณาUD-suffxเช่นกัน แต่เพราะมันตรงกับชนิดอื่นที่แท้จริงมันควรจะเป็นและไม่ได้เป็น UDL UD-ต่อท้ายที่กำหนดไว้ในไวยากรณ์เป็นตัวระบุ


ทำไมมันตีความว่าเป็น ud-suffix
วลาดจากมอสโก

@VladfromMoscow 0.เป็นเศษส่วนอย่างต่อเนื่อง ที่สามารถตามด้วย (ไม่รวมสิ่งของเลขชี้กำลัง) ud-suffix (สำหรับตัวอักษรที่ผู้ใช้กำหนด) หรือfloating-point-suffix (หนึ่งในfFlL) fสามารถพิจารณาUD-suffxเช่นกัน แต่เพราะมันตรงกับชนิดอื่นที่แท้จริงมันควรจะเป็นและไม่ได้เป็น UDL UD-ต่อท้ายที่กำหนดไว้ในไวยากรณ์เป็นตัวระบุ
1201 โปรแกรมเมื่อ

@ 1201ProgramAlarm: ในกรณีที่fสามารถตีความได้ว่าเป็น ud-suffix f.Tไม่ควรจะเป็น.ในตัวระบุ แต่มันคือ ... ฉันจะบอกว่าคอมไพเลอร์บั๊ก แต่ค่อนข้างแน่ใจว่ามันซับซ้อนกว่า
Jarod42
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.