Indeed, it is more complicated than it might seem.
Just to explicitly confirm the requirements:
- There should be no runtime calculations.
- Static, stack or heap memory should not be allocated, except for the actual result. (The assignment of executable code cannot be prohibited, but make sure that any data storage required by the CPU is confidential.)
In C ++, expressions can be lvalues or prvalues (before C ++ 11 and in C, r corresponds to the corresponding concept). Lvalues are objects, so they can be displayed on the L side of the eft side of an assignment expression. We want to avoid storing objects and lvalue-ness.
What you want is an identifier or id expression to evaluate to prvalue.
Currently, only counters can do this, but as you noticed, they leave much to be desired. Each enumeration declaration introduces a new, different type, therefore enum { Value = 123 }; introduces a constant that is not an integer, but its own unique type, which is converted to int . This is not the right tool for the job, although it works as a last resort.
You can use #define , but it is a hack since it completely avoids the parser. You must call it all uppercase letters, and then make sure that the same name "all-caps" is not used for anything else in the program. For library interfaces, such a guarantee is especially burdensome.
The next best option is to call the function:
constexpr int value() { return 123; }
Caution, however, as constexpr functions can still be evaluated at runtime. You need to jump over another hoop to express this value as a calculation:
constexpr int value() { constexpr int ret = 120 + 3; return ret; }
Now you cannot refer to a constant as a name, it must be value() . A function call statement may look less efficient, but this is the only current way to completely eliminate storage overhead.