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.