Я даже не уверен, разрешены ли отрицательные пользовательские литералы. Если нет, то почему они остались?
Например, я хотел бы использовать:
auto money_i_owe_jack = -52_jpy;
Это то, что я пытался с помощью gcc 4.7.2:
constexpr int64_t operator "" _jpy(long long l)
{
return static_cast<int64_t>(l);
}
ОШИБКА
Test_udl.cpp:60:47: error: ‘constexpr int64_t operator"" _jpy(long long int)’ has invalid argument list
Целочисленные литералы должны быть приняты как unsigned long long
, Отрицательный знак не является частью литерала, он применяется после факта к возвращаемому значению.
constexpr int64_t operator "" _jpy(unsigned long long l)
{
return static_cast<int64_t>(l);
}
Независимо от того, определены ли вы пользователем или нет, литералы целых и с плавающей точкой всегда положительны.
Причина довольно проста: если вы разрешаете использование отрицательных литералов, лексинг становится зависимым от контекста. То есть когда сталкиваешься с чем-то вроде - 10
лексер не может просто смотреть на этот текст изолированно и знать, должен ли он рассматриваться как два отдельных токена (-
а также 10
) или один (-10
). Если вы всегда рассматривали это как один токен, то что-то вроде a - 10
приведет к <a> and <-10>
(Т.е. <identifier><literal>
, что не является допустимой последовательностью в C ++ (или в большинстве других языков программирования).
Чтобы обойти это, парсер мог передать некоторый контекст лексеру, сообщая в любой момент, ожидать ли (например) оператора или операнда, чтобы он знал, что, если он должен произвести оператора, -
следует рассматривать как собственный знак, но если ожидался операнд, -10
будет один токен.
Как правило, гораздо проще иметь единственное правило, которому всегда следуют, и одно из них заключается в том, что -
всегда оператор, и литерал не может включать в себя -
совсем.