2

Suppose I want to define an integer literal which also allows for negative values, e.g. -12_km.

I.e., I would like to do

using coord_t = long long;
coord_t operator "" _km(long long int);

However, this is not accepted by my compiler (gcc).

The standard mentions a list of the allowed types for the parameter list of such a literal operator, but no signed integer type is among them.

Why is the standard like that? Why doesn't it allow for user-defined signed integer literals?

2 Answers 2

3

Because there are no negative integer literals in the grammar. Let's put aside the user-defined nature of your question. When we write -12, it's the literal 12, which has unary - applied to it. The grammatical definition of an integer literal contains no mention of a minus sign.

[lex.icon] (redacted and edited)

integer-literal:
    decimal-literal integer-suffix

decimal-literal:
    nonzero-digit
    decimal-literal digit

nonzero-digit: one of
    1  2  3  4  5  6  7  8  9

digit: one of 
    0 1 2 3 4 5 6 7 8 9

It's right there in the grammar. There are no productions that produce negative integer literal. And that is why user-defined literals follow the same convention. Their grammar production simply reuses the production for an integer literal

[lex.ext]

user-defined-literal:
    user-defined-integer-literal

user-defined-integer-literal:
    decimal-literal ud-suffix

Since negation is always an expression other than a literal, you need to overload the appropriate operator for coord_t. And by the way, the same applies for +12. It's a unary plus applied to 12, not a literal by itself.

Sign up to request clarification or add additional context in comments.

Comments

2

Because there are no negative integer literals in C++. -12 is actually the minus operator applying to the positive literal 12. That's the very reason why

So you need to overload the unary minus operator to use -12_km

coord_t operator "" _km(unsigned long long);
coord_t operator-();

6 Comments

I've got using coord_t = long long; and the compiler gives errors when I try to define the unary minus operator in that way. Is there any way around that?
@TimKuipers why do you overload without declaring a class? coord_t needs to be a struct or class. And you should also change the name because names ending with _t are reserved in POSIX: What are the rules about using an underscore in a C++ identifier?, Does the ISO 9899 standard has reserved any use of the _t suffix for identifiers?. In fact coord_t is also a common name so you'll have a high chance of name clashing
there's also Boost.Units that you can use if possible to avoid redefining unist yourself
thanks for the _t info. coord_t is not a class or struct, it's a typename for the primitive type long long.
@TimKuipers it's because your coord_t is just an alias of long long
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.