This is maybe a basic question, but I cannot see the response by myself right now.
Consider the following code:
template
struct T {
The currently accepted answer by SergeyA no longer holds as of C++17 (Definitions and ODR).
Every declaration is a definition, except for the following:
- ...
- (deprecated) Namespace scope declaration of a static data member that was defined within the class with the constexpr specifier
struct S {
static constexpr int x = 42; // implicitly inline, defines S::x
};
constexpr int S::x; // declares S::x, not a redefinition
Hence, as of C++17, I would use the static constexpr definition which is more expressive than the enum.
I suspect it's legacy code.
enum { value = (b ? 42 : 0) };
is valid code in C++03 as well as C++11.
static constexpr int value = (b ? 42 : 0);
is valid only in C++11.
Even more, is there any case for which one of them is not a viable solution?
Both are viable solutions in C++11. The choice of which one to use depends on a team. It's going to be a matter of a policy decision.
As the answer by SergeyA indicates, enum are true constants. You cannot ODR-use them. You can ODR-use a constexpr. Depending on which of these is desirable for your application, you can decide whether to use enums or constexprs.
There will be no noticeable difference for integral constants when used like this.
However, enum is actually better, because it is a true named constant. constexpr integral constant is an object which can be, for example, ODR-used - and that would result in linking errors.
#include <iostream>
struct T {
static constexpr int i = 42;
enum : int {x = 42};
};
void check(const int& z) {
std::cout << "Check: " << z << "\n";
}
int main() {
// check(T::i); // Uncommenting this will lead to link error
check(T::x);
}
When check(T::i) is uncommented, the program can not be linked:
/tmp/ccZoETx7.o: In function `main':ccc.cpp:(.text+0x45): undefined reference to `T::i'collect2: error:ldreturned1exit status
However, the true enum always works.