我是否应该始终在 class 之外定义一个 constexpr 静态数据成员?

Should I always define a constexpr static data member outside of the class?

为什么 constexpr static 数据成员需要在 C++11C++14 的 class 之外定义,但它不需要 [=15] 的要求=]、20 及以上?

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_);
}

问题的措辞很混乱。 static constexpr 自 C++11 起必须内联定义成员:

If a static data member of LiteralType is declared constexpr, it must be initialized with an initializer in which every expression is a constant expression, right inside the class definition:

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

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

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

Should I always define a constexpr static data member outside of the class?

总是?!只有西斯才讲究绝对。

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

D.1 Redeclaration of static constexpr data members [depr.static_constexpr]

1 For compatibility with prior C++ International Standards, a constexpr static data member may be redundantly redeclared outside the class with no initializer. This usage is deprecated. [ Example:

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

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

 — end example ]

它仍然受支持,因此您今天不必着手更新所有现有代码库。但它可能在未来被删除(三年,六年,也许九年后?)所以你将永远无法添加冗余声明。

如果您编写的 new 代码段 requires C++17 或更新版本,则无需添加此重新-出于某种原则的声明。