2015-11-12 14 views
8

Poniższy kod kompiluje zarówno GCC i Clang:Korzystanie zdefiniowane przez użytkownika literały w wyrażeniach czasami wymaga spacje

long double operator""_a(long double);  
auto x = 0e1_a+0; // OK 

Ale nie to (zastępując _a z _e):

long double operator""_e(long double); 
auto y = 0e1_e+0; // Error: unable to find numeric literal operator 'operator""_e+0' 

OTOH, to kod kompiluje:

auto z = 0e1_e +0; // OK 

Co się dzieje?

(To pytanie jest inspirowana przez this GCC bug report.)

Odpowiedz

13

Maksymalne strajki Munch ponownie.

[lex.pptoken]/P3:

Jeśli strumień wejściowy został przeanalizowany pod wyprzedzającym żetony aż do danego znaku:

  • [dwa wyjątki nie ma znaczenia tutaj]
  • W przeciwnym razie następny token przetwarzania wstępnego jest najdłuższym ciągiem znaków, który mógłby stanowić token przetwarzania wstępnego, nawet jeśli ten spowodowałby niepowodzenie dalszej analizy leksykalnej, z wyjątkiem tego, że: nazwa-nagłówka (2.8) jest tworzona tylko w ramach dyrektywy #include (16.2).

Problemem jest to, że 0e1_e+0, w przeciwieństwie 0e1_a+0 jest prawidłowy numer przerób ([lex.ppnumber]):

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

W rezultacie 0e1_e+0 jest analizowane jako jeden z PP numer token przetwarzania wstępnego, a następnie eksploduje później, ponieważ nie można go przekonwertować na ważny token (z oczywistych względów).

0e1_a+0, z drugiej strony, jest analizowany jako trzy tokeny, 0e1_a, + i 0, i wszystko jest dobrze.

+0

Tak się dzieje dla każdego nazwiska kończąc na "e" lub "E": / – Jarod42

Powiązane problemy