为什么constexpr数据成员不是隐式静态的?

时间:2016-03-17 09:22:38

标签: c++11 language-lawyer constexpr

如果你这样做:

constexpr int LEN = 100;

LEN变量定义为const,无需键入const关键字 它还具有static存储空间,无需键入static关键字。

另一方面,如果我们在class中执行相同操作:

struct A{
   constexpr static int SIZE = 100;
};

SIZE仍然定义为const,无需输入const关键字

SIZE不是static数据成员 您需要明确键入static。如果您没有编译错误。

问题是:
需要明确键入static的原因是什么?

3 个答案:

答案 0 :(得分:1)

static在两个上下文中都没有相同的含义:

  • 表示LENstatic表示“仅在此编译单元中可用”,因此只有内部链接。这是一个storage specifier
  • 代表A::SIZEstatic表示“它是类成员”,因此不会绑定到特定实例
类上下文中的

constexpr可以引用实例或类成员或函数,因此编译器无法在您的位置确定它是否为static绑定或不是特定的例子。它与const说明符的推理相同。但是,正如你可以想象的那样,拥有一个非静态的constexpr成员是没有意义的,所以它是被禁止的。示例:

class A
{
     int a;
     constexpr A(int value): a(value) {}

     // constexpr bound to a specific instance
     constexpr int getDouble() const
     {     return a*2;    }

     // constexpr not bound to a specific instance
     static constexpr int getDouble(int b)
     {     return b*2;    }
}
全局上下文中的

constexpr指的是在编译时计算的东西(或者,对于函数,如果不可能在编译时计算,将被内联),因此不需要外部链接等等,与static全局变量或函数相似的行为(仅可比较,因为使用编译时计算或内联,您也不需要内部链接)

constexpr int a = 5; // Will be replace everywhere by value

/* If b is constexpr, calcul are done at compile time and result will be used
* else double is inlined, so no need of linkage at all
*/
constexpr int getDouble(int b)  
{     return b * 2;     }

答案 1 :(得分:1)

constexpr不应该暗示static,因为constexpr 没有static是有道理的。考虑:

#include <iostream>

struct Dim
{
    constexpr Dim(int a,int b) : a(a), b(b) {}
    constexpr int Prod() const { return a*b; }
    int a,b;
};

int main()
{
    constexpr Dim sz(3,4);
    int arr[ sz.Prod() ];
    std::cout << sizeof(arr) << std::endl;
}

它也不应该在类定义之外隐含static 由于static表示“本地翻译单位”和constexpr 不需要。

答案 2 :(得分:0)

我认为你对static在全球范围内的含义感到困惑,而你的问题是基于这种误解。

  

LEN变量定义为const,无需键入const关键字。

当然constexpr暗示const,这不应该令人惊讶。

  

它还具有static存储空间,无需键入static关键字。

N.B。全局变量始终具有静态存储,因为它的生命周期是全局的。添加static关键字不会改变它,它的作用是给它内部链接,这意味着它不能通过当前翻译单元之外的名称访问。

constexprconst对全局变量的规则相同:命名空间范围const变量隐含地具有内部链接(这是&#34的多种含义之一;静态&#34;。)

但是类范围const变量没有内部链接,即使你向其添加static 。标记变量static意味着命名空间范围和类范围完全不同。将static自动添加到标记为constconstexpr的类成员没有意义,因为这意味着与命名空间范围内的变量完全不同。

所以constexpr暗示const(显然),在命名空间范围const意味着内部联系。

在班级范围constexpr仍然隐含const,但这对成员变量是否为&#34;类变量&#34;没有任何影响。或者&#34;实例变量&#34;。