Best way to determine compile time constants

What is the best way to define a simple constant value in C ++ 11 so that there is no penalty for execution? For example: (invalid code)

// Not ideal, no type, easy to put in wrong spot and get weird errors #define VALUE 123 // Ok, but integers only, and is it int, long, uint64_t or what? enum { Value = 123 }; // Could be perfect, but does the variable take up memory at runtime? constexpr unsigned int Value = 123; class MyClass { // What about a constant that is only used within a class, so // as not to pollute the parent namespace? Does this take up // memory every time the class is instantiated? Does 'static' // change anything? constexpr unsigned int Value = 123; // What about a non-integer constant? constexpr const char* purpose = "example"; std::string x; std::string metadata() { return this->x + (";purpose=" purpose); } // Here, the compiled code should only have one string // ";purpose=example" in it, and "example" on its own should not // be needed. }; 

Edit

Since I was told that this is a useless question, because there is no background, here is the background.

I define some flags so that I can do something like this:

 if (value & Opaque) { /* do something */ } 

The value of Opaque will not change at runtime, since it is only necessary at compile time, it seems silly to get it into my compiled code. The values ​​are also used inside the loop, which is executed several times for each pixel in the image, so I want to avoid runtime queries that will slow it down (for example, accessing the memory to get the constant value at runtime). This is not a "premature optimization, since the algorithm currently takes about one second to process the image, and I regularly process more than 100 images, so I want it to be as fast as possible.

Since people say this is trivial and not worry about it, I assume that #define as close to the literal value as possible, so maybe this is the best option to avoid “rethinking” the problem? I assume the general consensus is - you just hope that no one should ever use the word Opaque or other constants that you want to use?

+8
c ++ c ++ 11 constants idiomatic constexpr
source share
3 answers

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() { /* Computations that do not initialize constexpr variables (or otherwise appear in a constant expression context) are not guaranteed to happen at compile time, even inside a constexpr function. */ /* It OK to initialize a local variable because the storage is only temporary. There no more overhead here than simply writing the number or using #define. */ 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.

+7
source share

You will not be mistaken:

 static constexpr const unsigned int Value = 123; 

Honestly, try not to care about this. For example, really try.

+1
source share

I think you should consider C ++ 11 to indicate the base type for the enum , which is applicable to your example, would be

 enum : unsigned int { Value = 123 }; 

this removes one of your two objections to the use of enumerations, namely your inability to control which type will actually be used to represent them. However, it still does not allow nonintegral constants.

+1
source share

All Articles