静态 constexpr int 与老式枚举:何时以及为什么?

2021-12-29 00:00:00 enums c++ c++11 constexpr

这可能是一个基本问题,但我现在看不到自己的回复.

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

考虑以下代码:

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, "!");
}

我习惯于使用像 T 这样的结构,但我不止一次看到像 U 这样的结构用于相同的目的(主要是特征定义).

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).

据我所知,它们都是在编译时解决的,它们解决了几乎相同的问题,但在我看来 TU 更具可读性代码>(好吧,我知道,我的个人意见).

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?

推荐答案

请注意,以下答案不适用于 C++ 17 及更高版本.

这样使用时,积分常数不会有明显差异.

There will be no noticeable difference for integral constants when used like this.

然而,enum 实际上更好,因为它是一个真正的命名常量.constexpr 整数常量是一个对象,例如可以被 ODR 使用 - 这会导致链接错误.

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 << "
";
}

int main() {
    // check(T::i); // Uncommenting this will lead to link error
    check(T::x);
}

check(T::i)被取消注释时,程序无法链接:

When check(T::i) is uncommented, the program can not be linked:

/tmp/ccZoETx7.o:在函数`main'中:ccc.cpp:(.text+0x45): 未定义引用 `T::i' collect2:错误:ld 返回 1 退出状态

/tmp/ccZoETx7.o: In function `main': ccc.cpp:(.text+0x45): undefined reference to `T::i' collect2: error: ld returned 1 exit status

然而,真正的 enum 总是有效的.

However, the true enum always works.

相关文章