23

The following user defined literal emits an error:

constexpr double operator "" _kg(double q)
{
   return q*1000;
}

but if long is added the error will disappear and the code will work as follows:

constexpr double operator "" _kg(long double q)
{
   return q*1000;
}

the error is:

‘constexpr double operator""_kg(double)’ has invalid argument list

The problem is only caused by the argument and the return type can be double without long.

Why is long needed?

alfC
  • 14,261
  • 4
  • 67
  • 118
Sameh K. Mohamed
  • 2,323
  • 4
  • 29
  • 55

4 Answers4

25

C++11 draft n3290 has this to say about the parameters that user-defined literals can take (§13.5.8):

The declaration of a literal operator shall have a parameter-declaration-clause equivalent to one of the following:

const char*
unsigned long long int
long double
char
wchar_t
char16_t
char32_t
const char*, std::size_t
const wchar_t*, std::size_t
const char16_t*, std::size_t
const char32_t*, std::size_t

As you can see, double is not in that list, only long double is. So you have to use that for user-defined literals that expect a floating point number as an argument.

Community
  • 1
  • 1
Mat
  • 202,337
  • 40
  • 393
  • 406
  • Not really. I guess they just went for the largest type guaranteed to exist by the standard for the cooked literals. If you need more, you can always used raw literals. If you need less, well, just truncate. – Mat May 04 '15 at 08:07
  • I guess the reason is that for a literal, you can't know the precision. For example, some numbers have an infinite long representation in floating point format and thus need to be truncated. It makes sense to not early truncate the literals more than needed. – danijar Jul 12 '15 at 19:05
3

Only the following parameter lists are allowed on literal operators :

  • ( const char * ) (1)
  • ( unsigned long long int ) (2)
  • ( long double ) (3)
  • ( char ) (4)
  • ( wchar_t ) (5)
  • ( char16_t ) (6)
  • ( char32_t ) (7)
  • ( const char * , std::size_t ) (8)
  • ( const wchar_t * , std::size_t ) (9)
  • ( const char16_t * , std::size_t ) (10) ( const char32_t * , std::size_t ) (11)

    1. Literal operators with this parameter list are the raw literal operators, used as fallbacks for integer and floating-point user-defined literals (see above)

    2. Literal operators with these parameter lists are the first-choice literal operator for user-defined integer literals

    3. Literal operators with these parameter lists are the first-choice literal operator for user-defined floating-point literals

4-7. Literal operators with these parameter lists are called by

user-defined character literals

8-11. Literal operators with these parameter lists are called by user-defined string literals

Default arguments are not allowed C language linkage is not allowed Other than the restrictions above, literal operators and literal operator templates are normal functions (and function templates), they can be declared inline or constexpr, they may have internal or external linkage, they can be called explicitly, their addresses can be taken, etc.

From cpp reference: http://en.cppreference.com/w/cpp/language/user_literal

0

Stroustrup has a great section on string literals where he states (from the spec):

  • floating-point literal: accepted by a literal operator taking a single long double or const char* argument.

http://www.stroustrup.com/C++11FAQ.html#UD-literals

0

Although the failure of ANSI C to define a form of variable-argument declaration that can cleanly handle an extended-precision long double type whose format differs from from double has led to the type's being effectively deprecated on many platforms (unfortunate, IMHO, since it was a good type for use not only on systems with x87 coprocessors but also on systems with no FPU), the only sane way for a system with proper extended-precision types to handle a statement like:

long double a = 0.1;

is to have the 0.1 numeric literal start life as a long double equal to 14,757,395,258,967,641,293/147,573,952,589,676,412,928; it would be absurd to have that statement set a to 7,205,759,403,792,794/72,057,594,037,927,936 (roughly 0.10000000000000000555, the value of (double)0.1).

There might arguably be a few cases where having a numeric literal start life as a long double prior to getting down-converted might cause it to yield a different value from what it would if it started life as a double or float (e.g. the closest float to 9007199791611905.0 is 9007200328482816, which is 536870911 above the requested value, but (float)(double)9007199791611905.0 yields 9007199254740992, which is 536870913 below it. Of course, if one wants the float value 9007200328482816.0f, one should probably use a decimal representation that is closer to what one really wants.

supercat
  • 77,689
  • 9
  • 166
  • 211