替换常量:何时使用静态 constexpr 和内联 constexpr?

Jon*_*per 7 c++ constants constexpr c++17

这个问题是C++17的后续问题:仍然使用枚举作为常量?.

遗留常量有多种形式,特别是:

  • #define CONSTANT x
  • enum { CONSTANT = x };
  • const /*int/unsigned/whatever*/ CONSTANT = x;

关于static constexprinline constexpr常量作为替代的评论让我想到了更新我们许多遗留常量(特别是#define常量)的主题。

据我了解,一个inline constexpr值基本上只是被替换了,就像一个内联函数(我已经被证明是错误的)。相反,一个static constexpr值作为二进制的一部分存储在一个单独的区域中。假设我理解正确,什么时候应该优先选择另一个?我的预感是,对于积分常数,inline constexpr通常是首选。

Bar*_*rry 13

C++17 中全局常量的首选应该是:

inline constexpr int CONSTANT = 42;
Run Code Online (Sandbox Code Playgroud)

这将为您提供一个很好的一流变量,您可以在常量表达式中使用它,并且不会出现 ODR 问题。你可以参考一下。

宏带来了...作为宏的问题。枚举仅限于整数类型。对于constexpr变量,您可以拥有任何文字类型。在 C++20 中,您很可能可以疯狂地编写:

inline constexpr std::vector<int> small_primes = {2, 3, 5, 7, 11};
inline constexpr std::string cool_name = "Barry";
Run Code Online (Sandbox Code Playgroud)

这是允许这样做的唯一选项。


Aco*_*orn 5

在 C++17 中,#define在命名空间范围内的头文件中替换那些旧习语(例如)的正确方法是使用constexpr inline变量——而不是 static(暗示:它们已经具有内部链接)。

虽然通常您不会遇到 ODR 问题(因为诸如您描述的整数编译时常量很少被 ODR 使用,并且在inline函数中为它们的典型用法提供了规定),但最好将它们标记为inline现在我们有语言中的功能并避免所有问题。

请参阅标头中的 `const` 和 `constexpr` 变量是否应该是 `inline` 以防止 ODR 违规?有关它的技术细节。