Sintassi valida della chiamata dello pseudo-distruttore per una costante mobile


9

Considera il seguente programma dimostrativo.

#include <iostream>

int main()
{
    typedef float T;

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

Questo programma è compilato da Microsoft Visual Studio Community 2019.

Ma clanged gccemettere un errore come questo

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

Se scrivere l'espressione come ( 0.f ).T::~T()allora tutti e tre i compilatori compilano il programma.

Quindi sorge una domanda: questo record è 0.f.T::~T()sintatticamente valido? E se no, quale regola sintattica viene infranta?


1
Mettere uno spazio tra 0.fe .Tfa sì che sia GCC che Clang accettino questo ...
chris

1
Così come(0.f).T::~T();
cigien il

Un semplice float f = 1.0f.t;produrrà l'errore sul valore letterale numerico.
1201 Programma Allarme

Una floatè un built-in di tipo, non ha un distruttore di chiamare. Cosa stai facendo di chiamare manualmente i distruttori? Al di fuori del posizionamento-nuovo territorio, questo dovrebbe essere un grande no-no.
Jesper Juhl,

@JesparJuhl non è un distruttore ma uno pseudo distruttore, ho appena saputo che esiste. Le informazioni sui tag hanno un esempio (che ha anche una chiamata non giustificata al distruttore tra l'altro)
idclev 463035818

Risposte:


3

L'analisi dei token numerici è piuttosto grezza e consente molte cose che in realtà non sono numeri validi. In C ++ 98, la grammatica per un "numero di preelaborazione", che si trova in [lex.ppnumber], è

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

Qui, un "non-carattere" è qualsiasi carattere che può essere utilizzato in un identificatore, diverso dalle cifre, e un "segno" è + o -. Gli standard successivi estenderebbero la definizione per consentire virgolette singole (C ++ 14) e sequenze della forma p-, p +, P-, P + (C ++ 17).

Il risultato è che, in qualsiasi versione dello standard, mentre un numero di preelaborazione è necessario per iniziare con una cifra o un periodo seguito da una cifra, dopo di che può seguire una sequenza arbitraria di cifre, lettere e punti. Usando la regola del munch massimo, ne consegue che 0.f.T::~T();è necessario essere tokenizzati come 0.f.T :: ~ T ( ) ;, anche se 0.f.Tnon è un token numerico valido.

Pertanto, il codice non è sintatticamente valido.


È interessante notare che in realtà c'è un esempio con una discreta somiglianza in [lex.pptoken]: eel.is/c++draft/lex.pptoken#5
chris

1

Un suffisso letterale definito dall'utente, ud-suffix , è un identificatore . Un identificatore è una sequenza di lettere (inclusi alcuni caratteri non ASCII), il trattino basso e i numeri che non iniziano con un numero. Il carattere punto non è incluso.

Pertanto si tratta di un bug del compilatore poiché tratta la sequenza non identificativa f.Tcome identificatore.

La 0.è una frazionario costante , che può essere seguita da un esponente opzionale, e da una ud-suffisso (per un utente definito letterale) o un punto-suffisso floating (uno fFlL). La fpuò essere considerato un ud-suffx pure, ma dal momento che corrisponde un altro tipo letterale dovrebbe essere quello e non l'UDL. Un suffisso ud è definito nella grammatica come identificatore.


Perché viene interpretato come un suffisso ud?
Vlad da Mosca,

@VladfromMoscow The 0.è una costante frazionaria . Ciò può essere seguito da (escluso il materiale esponente) un suffisso ud (per un letterale definito dall'utente) o un suffisso in virgola mobile (uno di fFlL). La fpuò essere considerato un ud-suffx pure, ma dal momento che corrisponde un altro tipo letterale dovrebbe essere quello e non l'UDL. Un suffisso ud è definito nella grammatica come identificatore .
1201 Programma Allarme

@ 1201ProgramAlarm: considerando che fpuò essere interpretato come suffisso ud, f.Tnon come .non può essere nell'identificatore. ma è ... direi bug del compilatore ma abbastanza sicuro che sia più complicato.
Jarod42,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.