Değişken sabit için sözde yıkıcı çağırmanın geçerli sözdizimi


9

Aşağıdaki örnek programı düşünün.

#include <iostream>

int main()
{
    typedef float T;

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

Bu program tarafından derlenmektedir Microsoft Visual Studio Community 2019.

Ama clangve gccbu gibi bir hata sorunu

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

İfadeyi böyle yazmak için ( 0.f ).T::~T()her üç derleyici de programı derler.

Yani bir soru ortaya çıkıyor: bu kayıt 0.f.T::~T()sözdizimsel olarak geçerli mi? Ve eğer değilse, hangi sözdizimsel kural bozulur?


1
Arasına boşluk koymak 0.fve .Them GCC ve Clang neden olur ... bunu kabul etmek
Chris

1
As well as(0.f).T::~T();
cigien

Basit float f = 1.0f.t;, sayısal değişmezle ilgili hata üretir.
1201ProgramAlarm

A yerleşikfloat bir tiptir, aramanız için bir yıkıcı yoktur. Elle arama yapan yıkıcıları ne yapıyorsunuz? Yeni yerleşim bölgesinin dışında, bu büyük bir hayır-hayır olmalıdır.
Jesper Juhl

@JesparJuhl bu bir yıkıcı değil, sahte bir yıkıcı, bunun var olduğunu bilmeliyim. Etiket bilgisi bir örneğe sahiptir (bu da yıkıcı
btw'ye

Yanıtlar:


3

Sayısal belirteçlerin ayrıştırılması oldukça kaba ve aslında geçerli sayılar olmayan birçok şeye izin veriyor. C ++ 98'de, [lex.ppnumber] içinde bulunan bir "önişleme numarası" için dilbilgisi

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

Burada "nondigit", bir tanımlayıcıda basamaklar dışında kullanılabilen herhangi bir karakterdir ve "işareti" + veya - olur. Daha sonraki standartlar, tek tırnak (C ++ 14) ve p-, p +, P-, P + (C ++ 17) form dizilerine izin vermek için tanımı genişletecektir.

Sonuç olarak, standardın herhangi bir versiyonunda, bir ön işlem numarasının bir rakam veya bir nokta ve ardından bir rakam ile başlaması gerekirken, bundan sonra rasgele bir rakam, harf ve nokta dizisi gelebilir. Maksimal munch kuralını kullanarak, geçerli bir sayısal simge olmasa da , 0.f.T::~T();tokenleştirilmesi gereken izler .0.f.T :: ~ T ( ) ;0.f.T

Bu nedenle, kod sözdizimsel olarak geçerli değildir .


İlginç bir şekilde, aslında [lex.pptoken] 'de iyi benzerlik gösteren bir örnek var: eel.is/c++draft/lex.pptoken#5
chris

1

Kullanıcı tanımlı bir değişmez sonek, ud-sonek , bir tanımlayıcıdır . Bir tanımlayıcı bir sayı ile başlamaz (bazı ASCII olmayan karakterler dahil) harfler, alt çizgi ve sayı dizisidir. Dönem karakteri dahil değildir.

Bu nedenle, tanımlayıcı olmayan diziyi tanımlayıcı f.Tolarak ele aldığı için bir derleyici hatasıdır .

Bu 0., isteğe bağlı bir üs, ardından ya ud-soneki (kullanıcı tanımlı bir değişmez değer için) ya da bir kayan nokta-sonekini (bunlardan biri ) izleyebilen kesirli bir sabittir . Ayrıca bir ud-sonek olarak da düşünülebilir , ancak başka bir değişmez türle eşleştiği için UDL değil, bu olmalıdır. Bir ud-soneki , dilbilgisinde tanımlayıcı olarak tanımlanır.fFlLf


Neden ud-son eki olarak yorumlanıyor?
Vlad kimden Moskova

@VladfromMoscow 0.a, fraksiyonel sabit . Bunu (üs öğesi hariç) ud-son eki (kullanıcı tanımlı bir hazır bilgi için) veya bir kayan nokta son eki (bunlardan biri fFlL) izleyebilir . Ayrıca fbir ud-sonek olarak da düşünülebilir , ancak başka bir değişmez türle eşleştiği için UDL değil, bu olmalıdır. Bir ud-soneki , dilbilgisinde tanımlayıcı olarak tanımlanır .
1201ProgramAlarm

@ 1201ProgramAlarm: Oysa füd-eki olarak yorumlanabilir, f.Tolarak değil .tanımlayıcı olamaz. ama bu ... Derleyici hata diyorum ama daha karmaşık olduğundan eminim.
Jarod42
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.