【问题标题】:Should I always define a constexpr static data member outside of the class?我应该总是在类之外定义一个 constexpr 静态数据成员吗?
【发布时间】:2021-11-26 02:44:45
【问题描述】:

为什么constexpr static 数据成员需要在C++11C++14 上的类之外定义,但在c++ 1720 及更高版本上不需要这个要求?

struct Array{
    int static constexpr sz_ = 5;
    int ar_[sz_]{};
};

//int constexpr Array::sz_; // needed on `C++11`, `C++14` but not needed for C++17, C++20

void foo(int const& x){

}

int main(){
    foo(Array::sz_);
}
  • 那么这是标准的变化吗?还是我应该总是在类之外定义该成员?

【问题讨论】:

标签: c++ c++11 c++17


【解决方案1】:

问题的措辞非常混乱。 static constexpr 成员必须从 C++11 开始内联定义:

如果 LiteralType 的静态数据成员被声明为 constexpr,它必须 使用初始化程序进行初始化,其中每个表达式都是 常量表达式,就在类定义中:

https://en.cppreference.com/w/cpp/language/static

仅当此类成员被 ODR 使用时,C++11 中才需要单独定义。

自 C++17 起,static constexpr 成员是隐式内联的,因此 ODR 的使用不需要单独定义(尽管可以提供)。

【讨论】:

  • 我想你的意思是“隐式内联”
  • @UnholySheep 当然!
【解决方案2】:

我应该总是在类之外定义一个 constexpr 静态数据成员吗?

总是?!只有西斯在做绝对的事情。

C++17 使 static constexpr 变量隐式内联(在链接的意义上,它们总是需要一个类内初始化程序)。类外定义仍然是一个可选但已弃用的功能。

D.1 重新声明 static constexpr 数据成员 [depr.static_constexpr]

1 为了与以前的 C++ 国际标准兼容,一个 constexpr 静态数据成员可能在外部被冗余重新声明 没有初始化程序的类。此用法已弃用。 [ 示例:

struct A {
  static constexpr int n = 5;  // definition (declaration in C++ 2014)
};

constexpr int A::n;  // redundant declaration (definition in C++ 2014)

 — 结束示例 ]

它仍然受支持,因此您今天不必去更新所有现有的代码库。但它可能会在未来被删除(从现在起三年、六年、甚至九年?)所以你将无法永远添加多余的声明。

如果您编写了 段代码,需要 C++17 或更高版本,则出于某些原则,无需添加此重新声明。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多