Допустимый синтаксис вызова псевдодеструктора для плавающей константы - PullRequest
9 голосов
/ 17 апреля 2020

Рассмотрим следующую демонстрационную программу.

#include <iostream>

int main()
{
    typedef float T;

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

Эта программа компилируется Microsoft Visual Studio Community 2019.

Но clang и gcc выдают ошибку, подобную этой

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

Если написать выражение типа ( 0.f ).T::~T(), то все три компилятора компилируют программу.

Таким образом, возникает вопрос: является ли эта запись 0.f.T::~T() синтаксически допустимой? А если нет, то какое синтаксическое правило нарушено?

Ответы [ 2 ]

3 голосов
/ 18 апреля 2020

Синтаксический анализ числовых токенов довольно грубый и допускает множество вещей, которые на самом деле не являются действительными числами. В C ++ 98 грамматика для «числа предварительной обработки», найденного в [lex.ppnumber], равна

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

Здесь «nondi git» - это любой символ, который можно использовать в идентификатор, отличный от цифр, и «знак» - это либо +, либо -. Более поздние стандарты будут расширять определение, чтобы разрешить одинарные кавычки (C ++ 14) и последовательности в форме p-, p +, P-, P + (C ++ 17).

В результате в любой версии стандарта, хотя номер предварительной обработки должен начинаться с ди git или с точки, за которой следует ди git, после чего может следовать произвольная последовательность цифр, букв и периодов. Из правила максимального мунка следует, что 0.f.T::~T(); требуется для токенизации как 0.f.T :: ~ T ( ) ;, хотя 0.f.T не является допустимым числовым токеном.

Таким образом, код не синтаксически действителен.

1 голос
/ 17 апреля 2020

Пользовательский литеральный суффикс ud-суффикс является идентификатором . идентификатор - это последовательность букв (включая некоторые не-ASCII-символы), подчеркивание и цифры, которые не начинаются с цифры. Символ точки не включен.

Следовательно, это ошибка компилятора, поскольку он обрабатывает неидентификатор последовательности f.T как идентификатор.

0. - это дробная константа , за которой может следовать необязательный показатель степени, затем либо ud-суффикс (для пользовательского литерала), либо суффикс с плавающей точкой (один fFlL). f можно также считать ud-суффиксом , но, поскольку он соответствует другому литеральному типу, это должен быть именно он, а не UDL. ud-суффикс определяется в грамматике как идентификатор.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...