静态constexpr int vs老式枚举:何时以及为何?

sky*_*ack 23 c++ enums constexpr c++11

这可能是一个基本问题,但我现在无法看到自己的反应.

请考虑以下代码:

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, "!");
}
Run Code Online (Sandbox Code Playgroud)

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

据我所知,它们都是在编译时解决的,它们解决了几乎相同的问题,但在我看来,它T比可读性更强U(我知道,我个人意见).

我的问题非常简单:有哪种技术原因可以解决哪一种解决方案比另一种更好?
更有甚者,其中一个不是一个可行的解决方案吗?

Ser*_*eyA 25

当像这样使用时,积分常数没有明显的差别.

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

#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);
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

  • @skypjack [N4424](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4424.pdf) (2认同)

R S*_*ahu 5

我怀疑这是遗留代码。

enum { value = (b ? 42 : 0) };
Run Code Online (Sandbox Code Playgroud)

是 C++03 和 C++11 中的有效代码。

static constexpr int value = (b ? 42 : 0);
Run Code Online (Sandbox Code Playgroud)

仅在 C++11 中有效。

更重要的是,是否有任何情况下其中一个不是可行的解决方案?

两者都是 C++11 中的可行解决方案。选择使用哪个取决于团队。这将是一个政策决定的问题。

正如SergeyA回答所示,enum是真正的常数。您不能 ODR 使用它们。您可以 ODR 使用constexpr. 根据您的应用程序需要这些中的哪一个,您可以决定是使用enums 还是constexprs。


Tou*_*dou 5

SergeyA 目前接受的答案从C++17 开始不再成立(定义和 ODR)。

每个声明都是一个定义,但以下声明除外:

  • ...
  • (已弃用)使用 constexpr 说明符在类中定义的静态数据成员的命名空间范围声明
struct S {
    static constexpr int x = 42; // implicitly inline, defines S::x
};
constexpr int S::x; // declares S::x, not a redefinition
Run Code Online (Sandbox Code Playgroud)

因此,从 C++17 开始,我将使用静态 constexpr 定义,它比枚举更具表现力。