Подтвердить что ты не робот

Почему пользовательские строковые литералы и целочисленные литералы имеют другое поведение?

Я узнаю о пользовательских литералах и запутался со следующим тестовым кодом:

std::chrono::seconds operator"" _s(unsigned long long s) {
    return std::chrono::seconds(s);
}

std::string operator"" _str(const char *s, std::size_t len) {
    return std::string(s, len);
}

int main() {
    auto str = "xxxxx"_str;
    std::cout << str.size() << std::endl;    // works

    auto sec = 4_s;
    std::cout << sec.count() << std::endl;   // works

    std::cout << "xxxxx"_str.size() << std::endl;   // works

    std::cout << 4_s.count() << std::endl;   // does **NOT** work!

    return 0;
}

Компилятор выдает следующее сообщение об ошибке:

error: нет соответствующего литерал-оператора для вызова "operator" "_s.count" с аргументом типа "unsigned long long" или "const char *" и без соответствующего шаблона оператора литерала
     cout < 4_s.count() < епсИ;

Кажется, что он принимает _s.count как пользовательский литерал. Кроме того, литерал с плавающей запятой ведет себя как целочисленный литерал.

Почему пользовательские целые литералы и строковые литералы имеют другое поведение?

4b9b3361

Ответ 1

То, как работают литералы с плавающей точкой!!

Добавьте пару круглых скобок и он должен работать:

std::cout << (4_s).count();

Или, наоборот, отделите их (чтобы остановить компилятор от интерпретации его как плохо сформированного дробного постоянного литерала с плавающей запятой):

std::cout << 4_s .count();
//              ^ Space here!

Ссылка: CppReference.com

В разделе Примечания ссылки выше,

Из-за максимального munch, определяемых пользователем целых чисел и чисел с плавающей запятой, заканчивающихся на [ p, p, (начиная с С++ 17)] e и e, за которыми следуют операторы + или -, должен быть отделен от оператора пробелом в источнике:

long double operator""_E(long double);
long double operator""_a(long double);
int operator""_p(unsigned long long);

auto x = 1.0_E+2.0;  // error
auto y = 1.0_a+2.0;  // OK
auto z = 1.0_E +2.0; // OK
auto w = 1_p+2;      // error
auto u = 1_p +2;     // OK

Итак, когда дело доходит до точки, которая используется как десятичная точка, она должна быть отделена от чего-либо позади или будет рассматриваться как часть числа с плавающей запятой strong > .

Я тестировал пример выше из CppReference и получил сообщение о силимаре с очень сильным выражением:

test.cpp:19:10: error: unable to find numeric literal
operator 'operator""_E+2.0'
                    ^^^^^^
 auto x = 1.0_E+2.0;  // error

Получается, как _E+2.0 рассматривается как целое ud-суффикс?


Мое первоначальное объяснение можно найти в истории изменений этого сообщения.