5

I'm experimenting with C++ custom literals. I'm finding it strange that the simple function below stops working when I change the type from long double type to double, or when try to pass by reference.

At first I thought it had to do with the use of constexpr but that does not seem to be the case, as both of these work fine if it's not on an operator "", and removing the constexpr from the operator "" does not remove the error.

Are these well-thought-out decisions in the design of the language, or just nuances that my compiler (gcc 4.8.2) can't deal with?

// Conversion function, works fine with both long double and
// double, and with or without pass by reference.
constexpr long double to_deg (const long double& deg)
{
    return deg*M_PI/180.0;
}

// Custom literal with long double types and pass by value,
// works fine.
constexpr long double operator "" _deg (long double deg)
{
    return deg*M_PI/180.0;
}

// Custom literal with double types, gives "Invalid argument list."
// error.
constexpr double operator "" _deg (double deg)
{
    return deg*M_PI/180.0;
}

// Custom literal with pass by reference, gives "Invalid argument list." 
// error. Removing the const does not remove the error.
constexpr long double operator "" _deg (const long double& deg)
{
    return deg*M_PI/180.0;
}
MGA
  • 1,658
  • 15
  • 28
  • 2
    Because the language says that `double` as a parameter is not valid and that references aren't either. I'm not sure why you really need that to change. – chris Jul 25 '14 at 13:33
  • @chris It's not that I really need to change it, I'm just experimenting :). OK, I found the "only long double" specification, but I can't find anything about no references. – MGA Jul 25 '14 at 13:37
  • 2
    The standard lists the set of valid choices. References are not in there. For a perhaps more succinct version, you can try a [reference](http://en.cppreference.com/w/cpp/language/user_literal). – chris Jul 25 '14 at 13:39
  • @chris & quantdev Thanks! I'm not very familiar with interpreting the standard, so it did not occur to me that if a reference is not explicitly stated there, it's not allowed. I get it now. – MGA Jul 25 '14 at 14:12
  • Note that the type of the constant `180.0` is `double`. To use genuine `long double` constants add postfix `L`: `180.0L`. – Constructor Jul 28 '14 at 11:11

1 Answers1

5

The C++ Standard, section § 13.5.8 ( User-defined literals), lists all the valid types :

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

Neither double or double& , const long double& are listed here : so they are not allowed.

quantdev
  • 23,517
  • 5
  • 55
  • 88