Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++11 user-defined literals [duplicate]

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?".

like image 253
Khurshid Normuradov Avatar asked Aug 20 '13 06:08

Khurshid Normuradov


People also ask

What is a user-defined literal?

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.

What are literals in C ++ how many types of literals are allowed in C++?

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++.

Are literals stored in memory?

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.

What is a user-defined literal C++?

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.


1 Answers

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.

like image 154
dtech Avatar answered Sep 29 '22 02:09

dtech