簡體   English   中英

constexpr數組成員是否編譯時間常數?

[英]Are constexpr array members compile time constants?

是代碼片段

struct Parameters {
   static constexpr int n = 2;
   static constexpr double v[n] = {4.0, 5.0};
};

合法的C ++ 11? 並且,如果是這樣,是Parameters::v[0]Parameters::v[1]編譯時間常量或只是指針Parameters::v本身是constexpr (無論在編譯時意味着什么)?

正如您所看到的,我通常對constexpr數組及其在類/結構中的初始化感到困惑。 請隨時回答我的具體問題,並提及有關此主題的常見陷阱等。

我發現構造沒有問題。 引用C ++ 11, [dcl.constexpr]

constexpr說明符應僅適用於變量的定義,函數或函數模板的聲明,或文字類型的靜態數據成員的聲明(3.9)。 ...

§9對象聲明中使用的constexpr說明符將對象聲明為const 這樣的對象應具有文字類型並應初始化。 如果它是由構造函數調用初始化的,那么該調用應該是一個常量表達式(5.19)。 否則,或者如果在引用聲明中使用constexpr說明符,則其初始值設定項中出現的每個全表達式都應為常量表達式。 用於轉換初始化表達式和用於初始化的每個構造函數調用的每個隱式轉換都應該是常量表達式中允許的轉換之一(5.19)。

double是文字類型,文字類型也是如此。 這意味着代碼中的v[0]v[1]確實是常量表達式。

struct Parameters {
  static constexpr int n = 2;
  static constexpr double v[n] = {4.0, 5.0};
};

int main() {
  constexpr int a = Parameters::v[0];
  return 0;
}

gcc 4.8.2上的這段代碼編譯成如下:

0000000000000000 <main>:
   0:   55                      push   rbp
   1:   48 89 e5                mov    rbp,rsp
   4:   c7 45 fc 04 00 00 00    mov    DWORD PTR [rbp-0x4],0x4
   b:   b8 00 00 00 00          mov    eax,0x0
  10:   5d                      pop    rbp
  11:   c3                      ret 

所以是的,它是一個編譯時常量。

clang 3.4產生類似的代碼:

0000000000000000 <main>:
   0:   55                      push   rbp
   1:   48 89 e5                mov    rbp,rsp
   4:   b8 00 00 00 00          mov    eax,0x0
   9:   c7 45 fc 00 00 00 00    mov    DWORD PTR [rbp-0x4],0x0
  10:   c7 45 f8 04 00 00 00    mov    DWORD PTR [rbp-0x8],0x4
  17:   5d                      pop    rbp
  18:   c3                      ret

同樣,它是一個編譯時常量。

一切都是用-O0編譯的。

PS:如果a被聲明為const,那么對於gcc沒什么變化但是對於clang來說,值4不會直接移動,就好像是編譯時常量一樣。

如果a既不是const也不是constexpr,那么兩個編譯器都不能將Parameters :: v [0]視為編譯時常量。

struct Parameters {
   static constexpr int n = 2;
   static constexpr double v[n] = {4.0, 5.0};
};

就我所知,這個片段本身肯定是合法的。 第7.1.5節[dcl.constexpr]的C ++ 11標准說明了這一點

constexpr說明符只能應用於......文字類型的靜態數據成員的聲明

並且在3.9中定義了一個文字類型

類型是文字類型,如果它是:

- 標量類型; 要么...

- 一個文字類型的數組

因此,就我所知, static constexpr double v[2] = { ... }當然是有效的。

至於數組的成員是否是constexpr ...我不確定。 如果我們宣布

constexpr double d = Parameter::v[1];

那么g ++和clang都可以編譯它,但是clang版本無法鏈接到對Parameters::v的未定義引用。 我不知道這是否指向Clang錯誤,或者構造是否無效。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM