7

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

Lance Roberts
  • 22,383
  • 32
  • 112
  • 130
Khurshid Normuradov
  • 1,564
  • 1
  • 13
  • 20
  • 2
    Does it work for 1_000_000? I personally would use custom user literals and the letters K M G (kilo mega giga). – dtech Aug 20 '13 at 06:13
  • 1_000_000 compiled!!! – Khurshid Normuradov Aug 20 '13 at 06:16
  • @ddriver only problem with that is then you can't be as exact – aaronman Aug 20 '13 at 06:16
  • Why not, you can either 1_234 or you can 1.234K that will round to the same integer? @KhurshidNormuradov - you defined it only for _000, if you want more "precision" you need to have the `_` as a standalone postfix, that takes another parameter on the right which to use, but I don't know if this is possible. – dtech Aug 20 '13 at 06:19
  • 1
    This exact feature almost made it into C++14. Expect it to arrive in compilers around 2015 and formal standardization around 2017. http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3661.html – Potatoswatter Aug 20 '13 at 07:39

1 Answers1

4

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.

dtech
  • 47,916
  • 17
  • 112
  • 190
  • Yeah, you sort of solved the problem if the issue is many trailing zeroes, but you didn't solve it for the general case (e.g. `123456789` -> `123456.789K` -> `123.456789M` -> no clear benefit) – Lightness Races in Orbit Aug 20 '13 at 18:05
  • @LightnessRacesinOrbit - I agree it is pretty much pointless, however it is still useful as an example to the OP, who clearly got literals wrong. I actually had expectations for RHS parameter and chaining, it seems literals in their current form are rather rudimentary. – dtech Aug 20 '13 at 18:18