10

像这样写代码

struct S
{
    this() // compile-time error
    {
    }
}

给我一条错误消息说

default constructor for structs only allowed with @disable and no body.

为什么??

4

2 回答 2

14

这是比人们最初预期的要复杂得多的情况之一。

D 相对于 C++ 的一个重要且有用的特性是,每种类型(包括所有用户类型)都有一些可以在编译时评估的初始非垃圾值。它被用作T.init并有两个重要的用例:

  1. 模板约束可以使用 T.init 值来检查是否可以对给定类型执行某些操作(引用 Kenji Hara 的片段):

    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...
       }));
    }
    
  2. 除非您明确使用int i = void语法,否则您的变量始终会正确初始化。不可能有垃圾。

鉴于此,出现了难题。我们应该保证 T() 和 T.init 是相同的(正如许多来自 C++ 的程序员所期望的那样)还是允许可能很容易破坏该保证的默认构造。据我所知,尽管令人惊讶,但决定第一种方法更安全。

然而,讨论不断涌现,提出了各种改进(例如,允许 CTFE-able 默认构造函数)。最近出现了一个这样的线程。

于 2013-05-20T13:19:46.470 回答
10

它源于 D 中的所有类型都必须具有默认值这一事实。有相当多的地方使用类型的init值,包括默认初始化成员变量和在分配数组时默认初始化数组中的每个值之类的东西,并且init需要在编译时知道其中的一些情况。拥有init提供了很多好处,但它确实妨碍了拥有默认构造函数。

在所有使用的地方都需要使用真正的默认构造函数init(或者它不会是默认构造函数),但是在许多使用的情况下允许任意代码运行init充其量是有问题的。至少,您可能会被迫使其支持 CTFE 并且可能pure. 一旦你开始对它施加这样的限制,很快,你也可以直接将所有成员变量初始化为你想要的(这就是发生的情况init),因为你不会获得太多(如果任何东西),这将使默认构造函数变得毫无用处。

可能同时init拥有默认构造函数和默认构造函数,但随之而来的问题是何时使用一个而不是另一个,并且默认构造函数将不再是默认构造函数。更不用说,对于何时使用该init值以及何时使用默认构造函数,开发人员可能会感到非常困惑。

现在,我们确实有能力获取结构@disableinit值(这会导致其自身的一系列问题),在这种情况下,在任何需要的情况下使用该结构都是非法的init。因此,可能有一个默认构造函数可以在运行时运行任意代码,但我不知道它的确切后果是什么。但是,我敢肯定,在某些情况下,人们会希望有一个默认的构造函数init,因为它已经被 @disabled 了(比如声明类型的数组可能就是其中之一) .

因此,正如您所看到的,通过 D 所做的事情,与init其他语言相比,默认构造函数的整个问题变得更加复杂和成问题。

获得类似于默认构造的正常方法是使用 static 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;),并且静态opCall只会在S()显式使用时使用。但是如果你将它与@disable this()(禁用init属性)结合起来,那么你会得到类似于我之前描述的东西,我们可能有带有 @disabled 的默认构造函数init

我们最终可能会或可能不会将默认构造函数添加到语言中,但是由于init语言的工作方式和工作方式,添加它们存在许多技术问题,Walter Bright 认为不应该添加它们。因此,为了将默认构造函数添加到语言中,必须有人想出一个真正引人注目的设计来适当地解决所有问题(包括说服 Walter),我不希望会发生这种情况,但我们会看。

于 2013-05-20T18:31:27.613 回答