2014-05-01 30 views
17

是代碼片段constexpr數組成員是否編譯時間常量?

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數組及其在類/結構體中的初始化有點困惑。請隨時回答我的具體問題,並提及有關此主題的常見陷阱等。

+5

請注意'v'不是一個指針,它是一個數組。 – Angew

+0

似乎是完全合法的:http://ideone.com/oMwXAj –

+0

當x是const int \ [\]時,C++ 11中可能有[\'x \ [0 \] == 1 \ ?](http://stackoverflow.com/questions/18903113/x0-1-constant-expression-in-c11-when-x-is-const-int) –

回答

4

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

§1所述constexpr符應只適用於一個變量的定義中,的函數或 功能模板,或其中的一個靜態數據成員的聲明中的聲明文字類型(3.9)。 ...

§9A constexpr在對象聲明中使用的說明符將對象聲明爲const。這樣的對象應該具有文字類型並且應該被初始化。如果它是由構造函數調用初始化的,那麼這個調用應該是一個常量 表達式(5.19)。否則,或者如果在引用聲明中使用了constexpr說明符,則在其初始化程序中出現的每個完整表達式 應爲常量表達式。在初始化器表達式和用於初始化的每個構造器調用中,每個隱式轉換都應該是在常量表達式(5.19)中允許使用的那些 之一。

double是一個文字類型,所以是一個文字類型的數組。這意味着你的代碼中的v[0]v[1]確實是常量表達式。

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 

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

鐺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編譯的。

P.S:如果是聲明爲const,那麼GCC沒什麼變化,但對於鐺做,值4不直接彷彿是一個編譯時間常數mov'ed。

如果聲明既不是const或constexpr然後兩種編譯器無法處理參數:: v [0]作爲一個編譯時間常數。

2
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定義:

A型爲文本類型,如果它是:

- 標量類型;或...

- 文本類型

數組所以static constexpr double v[2] = { ... }肯定是有效的,據我可以告訴。

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

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

那麼這兩個g ++以及鐺編譯好的,但鐺版本失敗,一個未定義的參考Parameters::v鏈接。我不知道這是否指向Clang bug,或者構造是否無效。

+0

從技術上講,我不認爲數組的成員可以是'constexpr',因爲它們不是完全的對象。但是你無法直接訪問它們,只能通過表達式'Parameters :: v [0]'(或'1')訪問它們。這就滿足了一個常量表達式的所有要求。 – Angew

+0

@Angew但是從實際的角度來看,'Parameters :: v'的地址將由鏈接器或運行時設置,並且編譯器不知道。所以天真地說,'*(Parameters :: v + 1)'作爲'constexpr'會有點棘手? –

+1

'C++ 11 [expr.const]§2,3'定義常量表達式的reuqirements,並且數組解除引用不違反它們中的任何一個。所以這是一個不變的表達。 – Angew

相關問題