2013-10-24 51 views
18

靜態整型數據成員可以聲明constconstexpr,但在類定義中初始化非整數的靜態數據成員必須是constexpr爲什麼必須在類中初始化非整型靜態數據成員才能使用?在類定義初始化

class MyClass { 
    static const  int w = 5;   // okay 
    static constexpr int x = 5;   // okay 
    static const  float y = 1.5;  // error! 
    static constexpr float z = 1.5;  // okay 
}; 

有誰知道爲什麼Y的聲明不允許?標準中違規的部分是9.4.2/3,但是爲什麼是非法的?

+0

歷史,遺產,進化,傳統? –

+0

以上所有? – bstamour

+0

你看着[這個答案](http://stackoverflow.com/questions/2454019/why-arent-static-const-floats-allowed)? –

回答

3

此前C++ 11,你不能在類聲明中初始化非整數/枚舉類型的靜態成員(但你可以在類的聲明外)。管理constexpr規則攜帶着,但允許你在類聲明中使用constexpr(所以你不需要像下面的代碼了)來初始化它:

struct A 
{ 
    static const float pi; 
}; 

const float A::pi = 3.1415; 

一個此規則的副作用是簡化你的類結構而不是醜陋(像上面的代碼)。

在C++ 11添加constexpr之前,這種情況的原因之一是標準沒有指定如何實現浮點(它留給處理器/體系結構 - 例如,當你說float x = 1.6f,它實際上是在大多數系統1.6000000000024)。

+0

你有正確的想法,但是一個不好的例子。 1.5f可以精確地表示爲二進制或十進制浮點類型,並且在任何系統上都應該精確地保存爲1.5。 – hvd

+0

@ hvd整個觀點是你不能依賴它,因爲它依賴於平臺。 –

+0

你寫過「它實際上是大多數系統上的1.499999999999999」,這不僅僅是說它不需要精確存儲。如果您發現任何未準確存儲的系統,即使您的系統允許,我也會非常驚訝。 – hvd

0

這可能是因爲一個事實,即非積分我還可以包括數據類型,比如CHAR,這就是爲什麼你不能讓他們不斷和需要的整體情況不斷expression.But,你可以讓他們常量表達式或不變。所以,因爲char只能是一個常量表達式,所以對於所有非整數值都是非法的。

2

float是有點困難之一來描述的動機,但是想象一下,一個類成員:

class MySpecialInt { 
public: 
    constexpr MySpecialInt(const int & other) { 
    } 
}; 
class MyClass { 
    static const  MySpecialInt a = 5; // error 
    static constexpr MySpecialInt b = 5; // okay 
}; 

a在這種情況下可能有一些潛在的違反不平凡的建設(或最不復雜的是)一個定義規則。因爲constexpr保證了限制性編譯時的特性,b的拷貝構造必須也有constexpr,因此保證在編譯時返回一個良好定義的值(和NOT違反一定義規則)

爲什麼float存在這種行爲,我相信只是遺留原因,因爲float從未傳統初始化,能夠像這樣(「因爲標準是這樣說的」),所以他們抓住了constexpr傘下初始化staticconstfloat成員。

+0

我很想知道更多關於ODR如何應對這個問題的細節。每個'a'和'b'必須被初始化一次。這意味着恰當的構造函數必須被調用一次。在'a'的情況下,我們不知道在編譯期間或運行時是否會出現構造,但是可以在多少條件下定義'a','b'或MySpecialInt'構造函數(例如這是由於使用'constexpr'與'const')? – KnowItAllWannabe

+0

它們實際上是爲每個翻譯單元定義的。所以如果你把這個類包含在兩個地方,'a'和'b'被定義了兩次,但是因爲'b'是'constexpr'它保證了始終如一的值,所以它是合法的。 'a'可能會有一些內部計數器或其他邏輯,這會導致翻譯單元之間出現'a',這就是爲什麼將它聲明爲僅僅是static''const'是非法的原因。 –

+0

根據9.4.2/3,使用初始值設定項的靜態數據成員的聲明不是定義,如果這些成員是odr-used使用的,那麼這些成員的定義在類之外是必需的。但是,如果存在的話,你引用的問題同樣適用於'const' - 而不是'constexpr' - 動態初始化的整型類型的成員。被調用來產生初始化值的函數可能會在不同的調用中返回不同的值。所以我不明白這是如何解釋非整數靜態數據成員的限制。 – KnowItAllWannabe

相關問題