struct S
{
this() // compile-time error
{
}
}
編寫代碼給我一個錯誤消息說
default constructor for structs only allowed with @disable and no body.
爲什麼?
struct S
{
this() // compile-time error
{
}
}
編寫代碼給我一個錯誤消息說
default constructor for structs only allowed with @disable and no body.
爲什麼?
這是一個比最初期望的更棘手的情況之一。
D對C++的重要和有用的特性之一是每一種類型(包括所有的用戶類型)都有一些可以在編譯時評估的初始非垃圾值。它是用來作爲T.init
,有兩個重要的用途:
模板約束可以使用T.init值來檢查,如果某些操作可以在給定類型進行(引用原賢治的片段):
template isSomething(T) {
enum isSomething = is(typeof({
//T t1; // not good if T is nested struct, or has @disable this()
//T t2 = void; auto x = t2; // not good if T is non-mutable type
T t = T.init; // avoid default construct check
...use t...
}));
}
除非明確使用int i = void
語法,否則您的變量始終會被正確初始化。沒有垃圾可能。
鑑於此,出現了難題。我們是否應該保證T()和T.init是相同的(因爲許多來自C++的程序員會期望)或者允許可能容易破壞該保證的默認構造。據我所知,做出的決定是,儘管令人驚訝,但第一種方法更安全。然而,討論不斷出現各種改進建議(例如,允許CTFE可以使用的默認構造函數)。一個such thread已經出現在最近。
它源於D中的所有類型必須具有默認值的事實。在類型的init
值有很多地方被使用,其中包括像默認初始化成員變量這樣的東西,以及在分配時默認初始化數組中的每個值,並且編譯時需要知道init
。有init
提供了很多好處,但它確實阻礙了默認的構造函數。
一個真正的默認構造函數就不需要在所有使用init
的地方使用(或它不會是默認值),但允許任意代碼在的一定數量的init
使用的情況下運行會充其量是有問題的。至少,你可能會被迫使它成爲CTFE能力,並可能是pure
。只要你開始對它進行限制,很快你就可以直接將所有成員變量初始化爲你想要的(這是init
的情況),因爲你不會獲得太多(如果有的話),這將使默認的構造函數非常無用。
可能可以同時擁有init
和默認構造函數,但隨後的問題來了作爲一個時使用過其他的,並且默認的構造函數不會真的是默認了到。更不用說,開發人員可能會對使用init
值的時間以及何時使用默認構造函數感到困惑。現在
,我們做有@disable
一個struct的init
值(這將導致其自身的問題),在這種情況下,這將是非法的使用結構中,需要init
任何局勢的能力。因此,可能有一個默認的構造函數可以在運行時運行任意代碼,但是我不知道這個結果的確切後果。然而,我確信有些情況下人們會希望有一個默認的構造函數,需要init
,因此它不起作用,因爲它是@disabled(像聲明類型的數組可能是其中之一)。
因此,正如您所看到的,通過執行D與init
所做的操作,使默認構造函數的整個問題比其他語言更加複雜和有問題。
獲取類似於默認構造的常規方法是使用靜態的opCall
。喜歡的東西
struct S
{
static S opCall()
{
//Create S with the values that you want and return it.
}
}
然後,每當你使用S()
- 例如
auto s = S();
,靜態opCall
被調用,你會得到這是在運行時創建的值。但是,S.init
仍將用於之前的任何位置(包括S s;
),並且僅在明確使用S()
時纔會使用靜態opCall
。但是,如果你將它與@disable this()
(它禁用了init
屬性)相結合,那麼你就會得到類似於我之前描述的,我們可能使用@disabled init
的默認構造函數。
我們可能會或可能不會與缺省構造被添加到最終的語言結束了,但還有一些技術問題,他們將因如何init
和語言文字工作,和沃爾特亮不認爲他們應該被添加。因此,對於默認的構造函數加入到語言中,有人必須提出一個非常有吸引力的設計,以適當解決所有問題(包括說服Walter),並且我並不期望這樣做,但我們會看到。