I'm learning C++11, and am interested in user-defined literals. So I decided to play a bit with it. Some languages have a syntax like this:
int n = 1000_000_000;
I tried to simulate this feature in C++11.
inline constexpr unsigned long long operator "" _000 (unsigned long long n)noexcept
{
return n * 1000;
}
inline constexpr unsigned long long operator "" _000_000 (unsigned long long n)noexcept
{
return n * 1000*1000;
}
inline constexpr unsigned long long operator "" _000_000_000 (unsigned long long n)noexcept
{
return n * 1000*1000*1000;
}
int main(){
constexpr auto i = 100_000; // instead of 100000
constexpr auto j = 23_000_000; // instead of 23000000;
}
But for the general case I couldn't simulate it, i.e.
auto general_case = 123_456_789; //can't compile
My question is "Can I simulate for the general case as above using C++11?".
In a raw user-defined literal, the operator that you define accepts the literal as a sequence of char values. It's up to you to interpret that sequence as a number or string or other type. In the list of operators shown earlier in this page, _r and _t can be used to define raw literals: C++ Copy.
Generally, both terms, constants, and literals are used interchangeably. For example, “const int = 5;“, is a constant expression and the value 5 is referred to as a constant integer literal. There are 4 types of literal in C and five types of literal in C++.
The characters of a literal string are stored in order at contiguous memory locations. An escape sequence (such as \\ or \") within a string literal counts as a single character.
A literal is used for representing a fixed value in a program. A literal could be anything in a code like a, b, c2. , 'ACB', etc. Similarly, User-Defined Literals (UDL) provides literals for a variety of built-in types that are limited to integer, character, floating-point, string, boolean, and pointer.
This is not possible with user defined literals in the C++11 version of the language as it is right now. User defined literals support a limited format for parameters, doesn't seem to support a right side parameter, chaining, plus there is the problem of representing numbers that begin with 0 as actual numbers. So it is a no go.
You current approach defines _000 and so on as standalone literals, so the compiler will only work with them and no other. It is not like the _
is the operator and the 000
is some parameter you can work with unfortunately.
You could however use letter suffixes instead.
long long constexpr operator"" K (long double n) {
return n * 1000;
}
long long constexpr operator"" M (long double n) {
return n * 1000000;
}
long long constexpr operator"" G (long double n) {
return n * 1000000000;
}
And then:
0.05M == 50000;
123.232K == 123232
1.000000001G == 1000000001
Surely, the last case sort of defeats the purpose, because once again you have many zeroes without visual indication... So you can go for something like:
1.G + 1 == 1000000001 // much clearer 1 billion + 1
This makes it a little ugly, since the literal expects a real number and won't work with an integer unless you define an extra literal just to use with integers. Then you can simply use 1G instead.
Also, this approach will likely produce compiler warnings, apparently the c++ group wants to reserve all suffixes that are not preceded by underscore for "future uses". If you want the warnings gone, just use _K _M and _G instead.
EDIT: I removed the initializer list solution, because it produces invalid results with numbers like 010, which is processed as octal and mess up the calculations.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With