Static constexpr int vs old-fashioned enum: when and why?

怎甘沉沦 提交于 2019-12-17 16:12:27

问题


This is maybe a basic question, but I cannot see the response by myself right now.

Consider the following code:

template<bool b>
struct T {
    static constexpr int value = (b ? 42 : 0);
};

template<bool b>
struct U {
    enum { value = (b ? 42 : 0) };
};

int main() {
    static_assert(T<true>::value == 42, "!");
    static_assert(T<false>::value == 0, "!");
    static_assert(U<true>::value == 42, "!");
    static_assert(U<false>::value == 0, "!");
}

I'm used to using structs like T, but more than once I've seen structs like U used for the same purpose (mostly traits definition).

As far as I can see, they are both resolved at compile time and they solve almost the same problem, but it seems to me that T is far more readable than U (well, I know, my personal opinion).

My question is pretty simple: is there any technical reason for which one solution is better than the other one?
Even more, is there any case for which one of them is not a viable solution?


回答1:


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: ld returned 1 exit status

However, the true enum always works.




回答2:


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.




回答3:


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.



来源:https://stackoverflow.com/questions/37259807/static-constexpr-int-vs-old-fashioned-enum-when-and-why

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!