Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are user-defined-literals resolved at compile-time or runtime?

I wonder, because predefined literals like ULL, f, etc. are obviously resolved at compile time. The standard (2.14.8 [lex.ext]) doesn't seem to define this, but it seems to tend towards runtime:

[2.14.8 / 2]
A user-defined-literal is treated as a call to a literal operator or literal operator template (13.5.8). To determine the form of this call for a given user-defined-literal L with ud-suffix X, the literal-operator-id whose literal suffix identifier is X is looked up in the context of L using the rules for unqualified name lookup (3.4.1). Let S be the set of declarations found by this lookup. S shall not be empty.
(emphasis mine.)

However, to me this seems to introduce unnecessary runtime-overhead, as literals can only be appended to values that are available at compile-time anyways like 13.37f or "hello"_x (where _x is a user-defined-literal).
Then, we got the templated user-defined-literal, that never really gets defined in the standard AFAICS (i.e., no example is given, please prove me wrong). Is that function somehow magically invoked at compile time or is it still runtime?

like image 763
Xeo Avatar asked Apr 16 '11 03:04

Xeo


1 Answers

Yes, you get a function call. But function calls can be compile time constant expressions because of constexpr literal operator functions.

For an example, see this one. As another example to show the advanced form of constexpr computations allowed by the FDIS, to have compile time base-26 literals you can do

typedef unsigned long long ull;

constexpr ull base26(char const *s, ull ps) {
  return (*s && !(*s >= 'a' && *s <= 'z')) ? throw "bad char!" :
    (!*s ? ps : base26(s + 1, (ps * 26ULL) + (*s - 'a')));
}

constexpr ull operator "" _26(char const *s, std::size_t len) {
  return base26(s, 0);
}

Saying "bcd-"_26 will evaluate a throw-expression, and thereby cause the return value to become non-constant. In turn, it causes any use of "bcd-"_26 as a constant expression to become ill-formed, and any non-constant use to throw at runtime. The allowed form "bcd"_26 evaluates to a constant expression of the respective computed value.

Note that reading from string literals is not explicitly allowed by the FDIS, however it presents no problem and GCC supports this (the character lvalue reference is a constant expression and the character's value is known at compile time). IMO if one squints, one can read the FDIS as if this is allowed to do.

Then, we got the templated user-defined-literal, that never really gets defined in the standard AFAICS (i.e., no example is given, please prove me wrong)

The treatment of literals as invoking literal operator templates is defined in 2.14.8. You find more examples at 13.5.8 that detail on the literal operator function/function templates itself.

Is that function somehow magically invoked at compile time or is it still runtime?

The keyword is function invocation substitution. See 7.1.5.

like image 59
Johannes Schaub - litb Avatar answered Sep 25 '22 12:09

Johannes Schaub - litb