Pertimbangkan program demonstratif berikut.
#include <iostream>
int main()
{
typedef float T;
0.f.T::~T();
}
Program ini disusun oleh Microsoft Visual Studio Community 2019
.
Tapi clang
dan gcc
keluarkan kesalahan seperti ini
prog.cc:7:5: error: unable to find numeric literal operator 'operator""f.T'
7 | 0.f.T::~T();
| ^~~~~
Jika menulis ekspresi seperti itu ( 0.f ).T::~T()
maka ketiga kompiler mengkompilasi program.
Maka timbul pertanyaan: apakah rekaman ini secara 0.f.T::~T()
sintaksis valid? Dan jika tidak, lalu aturan sintaksis apa yang dilanggar?
c++
syntax
floating-point
c++17
pseudo-destructor
Vlad dari Moskow
sumber
sumber
0.f
dan.T
menyebabkan GCC dan Dentang menerima ini ...(0.f).T::~T();
float f = 1.0f.t;
akan menghasilkan kesalahan tentang literal numerik.float
adalah tipe bawaan , ia tidak memiliki destruktor untuk Anda panggil. Apa yang bahkan Anda lakukan secara manual memanggil destruktor? Di luar wilayah penempatan baru, yang harus menjadi besar tidak-tidak.Jawaban:
Penguraian token numerik cukup kasar, dan memungkinkan banyak hal yang sebenarnya bukan angka yang valid. Di C ++ 98, tata bahasa untuk "nomor preprocessing", ditemukan di [lex.ppnumber], adalah
Di sini, "nondigit" adalah karakter apa pun yang dapat digunakan dalam pengidentifikasi, selain digit, dan "tanda" adalah + atau -. Standar selanjutnya akan memperluas definisi untuk memungkinkan tanda kutip tunggal (C ++ 14), dan urutan bentuk p-, p +, P-, P + (C ++ 17).
Hasilnya adalah bahwa, dalam versi standar apa pun, sementara nomor praproses diperlukan untuk memulai dengan digit, atau periode yang diikuti oleh digit, setelah itu urutan angka, huruf, dan periode yang sewenang-wenang dapat mengikuti. Menggunakan aturan munch maksimal, maka yang
0.f.T::~T();
diperlukan adalah tokenized0.f.T :: ~ T ( ) ;
, meskipun0.f.T
bukan token numerik yang valid.Dengan demikian, kode tersebut tidak valid secara sintaksis.
sumber
Sufiks literal yang ditentukan pengguna, ud-suffix , adalah pengidentifikasi . Sebuah identifier adalah urutan huruf (termasuk beberapa karakter non-ASCII), garis bawah, dan angka yang tidak dimulai dengan angka. Karakter periode tidak termasuk.
Oleh karena itu itu adalah bug kompiler karena memperlakukan urutan non-pengidentifikasi
f.T
sebagai pengidentifikasi.Ini
0.
adalah konstanta fraksional , yang dapat diikuti oleh eksponen opsional, lalu sufiks ud (untuk literal yang ditentukan pengguna) atau sufiks floating-point-suffix (salah satu darifFlL
). Ituf
dapat dianggap sebagai suf-suffx juga, tetapi karena cocok dengan tipe literal yang lain, seharusnya demikian dan bukan pada UDL. Sebuah ud-akhiran didefinisikan dalam tata bahasa sebagai identifier.sumber
0.
adalah konstanta pecahan . Itu dapat diikuti oleh (tidak termasuk hal-hal eksponen) akhiran -ud (untuk literal yang ditentukan pengguna) atau akhiran titik-mengambang (salah satu darifFlL
). Ituf
dapat dianggap sebagai suf-suffx juga, tetapi karena cocok dengan tipe literal yang lain, seharusnya demikian dan bukan pada UDL. Sebuah ud-akhiran didefinisikan dalam tata bahasa sebagai identifier .f
dapat diartikan sebagai ud-suffix,f.T
tidak.
boleh tidak bisa di identifier. tapi itu ... Saya akan mengatakan bug compiler tetapi cukup yakin itu lebih rumit.