Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Which should I prefer for a constant within a function: constexpr const or enum?

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?

like image 514
einpoklum Avatar asked Apr 24 '17 18:04

einpoklum


People also ask

Should I use const or constexpr?

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.

Is constexpr the same as static const?

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 .

What is the difference between enum and #define constant in C?

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!

Should constexpr be static?

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.


1 Answers

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.

like image 170
Yakk - Adam Nevraumont Avatar answered Oct 13 '22 17:10

Yakk - Adam Nevraumont