Ошибка компиляции при использовании члена пользовательского литерала

При компиляции этого кода (без заголовка)

template <typename T>
struct Temperature {
    T temp;

    explicit Temperature(T t)
        : temp(t)
    {}
};

Temperature<long double> operator "" _f (long double t)
{
    return Temperature<long double>((t - 32) / 1.8);
}

int main()
{
    auto t = 100.0_f;
    t.temp;

    100.0_f.temp; // ERROR AT THIS LINE
    return 0;
}

Компиляторы (как g++ 4.8, так и клан g++ 3.4 на Ubuntu 14.04) будут жаловаться, что

error: unable to find numeric literal operator ‘operator"" _f.temp
     100.0_f.temp;
     ^

Кажется, что _f.temp считается суффиксом. Почему компиляторы разбирают это так, вместо того, чтобы останавливаться на точке?

Ответы

Ответ 1

Номера предварительной обработки - это странные звери, которые в большинстве случаев предназначены для упрощения записи препроцессора.

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 p sign
    pp-number P sign
    pp-number .

12 - действительный токен числа pp, так что 0xe+foo (см. Пример в [lex.pptoken]/4), и так. .12.CA'TS_RULE..56.me+owp-urr. Если последние два делают его прошлой фазой перехода 6, то программа плохо сформирована, потому что она не может быть преобразована в действительный токен в фазе 7. До тех пор, однако, это действительно так, поэтому максимальный мунк говорит, что мы анализируем 0xe+foo или 100.0_f.temp как один токен предварительной обработки.