I'm used to definition my constants with enum { my_const = 123; }
, since in classes, using static constexpr
requires some code outside of the class definition (see this question). But - what about in function bodies? Lately I've been noticing people just having constexpr
variables in their functions (not even bothering to const
them actually), and I was wondering whether I'm a fool who's behind the times with my
int foo(int x)
{
enum : int { bar = 456 };
return x + bar;
}
So, my question is: Is there any benefit to using enum's within function bodies rather than constexpr variables?
The primary difference between const and constexpr variables is that the initialization of a const variable can be deferred until run time. A constexpr variable must be initialized at compile time.
constexpr variable is guaranteed to have a value available at compile time. whereas static const members or const variable could either mean a compile time value or a runtime value. Typing constexpr express your intent of a compile time value in a much more explicit way than const .
One of the differences between the two is that #define is a pre-processor directive while enum is part of the actual C language. #define statements are processed by the compiler before the first line of C code is even looked at!
The short answer is that not only is static useful, it is pretty well always going to be desired. First, note that static and constexpr are completely independent of each other. static defines the object's lifetime during execution; constexpr specifies that the object should be available during compilation.
You can accidentally or on purpose force ODR-existence of bar
if it was a constexpr int bar = 456;
, this is not possible with enum : int { bar = 456 };
.
This may or may not be an advantage on either side.
For example
int baz(int const* ptr ) {
if (ptr) return 7; return -1;
}
int foo(int x)
{
// enum : int { bar = 456 };
constexpr int bar = 456;
return x + baz(&bar);
}
the enum
version doesn't compile, the constexpr int
one does. A constexpr int
can be an lvalue, an enumerator (one of the listed enum constants) cannot.
The enum values aren't actually an int
, while the constexpr int
is actually an int
. This may matter if you pass it to
template<class T>
void test(T) {
static_assert(std::is_same<T,int>::value);
}
one will pass the test; the other will not.
Again, this could be an advantage, a disadvantage, or a meaningless quirk depending on how you are using the token.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With