在没有writeln的情况下找不到构造函数

时间:2013-07-16 10:07:37

标签: oop compiler-errors d

我在Ubuntu 13.04 64位上使用DMD64 D Compiler v2.063.2。

我写了一个课程如下:

class FixedList(T){
    // list
    private T[] list;

    // number of items
    private size_t numberOfItems;

    // capacity
    private size_t capacity;

    // mutex
    private Mutex listMutex;

    // get capacity
    @property public size_t Capacity(){ return capacity; }
    @property public shared size_t Capacity(){ return capacity; }

    // constructor
    public this( size_t capacity ){
        // initialise
        numberOfItems = 0;
        this.capacity = capacity;

        writeln("Cons Normal");
    }

    // constructor
    public shared this( size_t capacity ){
        // initialise
        numberOfItems = 0;
        this.capacity = capacity;

        // create mutex
        listMutex = cast(shared)(new Mutex());

        writeln("Cons Shared");
    }
}

虽然类以这种方式编写,但在main函数中,我编写了代码:

auto list1 = new shared FixedList!int( 128 );
auto list2 = new FixedList!int( 128 );

使用此输出,根本没有错误,输出如下:

Cons Shared
Cons Normal

接下来我要做的是从代码中删除writeln行,当我重新编译代码时,它会开始显示错误消息,如下所示:

src/webapp.d(61): Error: constructor lists.FixedList!(int).FixedList.this called with argument types:
    ((int) shared)
matches both:
    lists.d(28): lists.FixedList!(int).FixedList.this(ulong capacity)
and:
    lists.d(37): lists.FixedList!(int).FixedList.this(ulong capacity)
src/app.d(61): Error: no constructor for FixedList
src/app.d(62): Error: constructor lists.FixedList!(int).FixedList.this called with argument types:
    ((int))
matches both:
    lists.d(28): lists.FixedList!(int).FixedList.this(ulong capacity)
and:
    lists.d(37): lists.FixedList!(int).FixedList.this(ulong capacity)
src/app.d(62): Error: no constructor for FixedList
make: *** [all] Error 1

基本上writeln函数可以防止错误。实际上writeln在许多地方都在预防,我不确定为什么会发生这种情况。

我甚至尝试使用m32标志编译32位代码,但它仍然是相同的。我做错了什么,或者这是一个错误?

2 个答案:

答案 0 :(得分:3)

purenothrow@safe是模板函数的推断。由于FixedList是模板化的,因此它的构造函数是模板化的。 writeln不是(也不可能)pure,因为它是I / O.因此,虽然writeln在构造函数中,但它们被推断为不是pure,但构造函数正在执行的所有其他操作都是pure,因此无需调用writeln ,他们成为pure

在某些情况下,编译器可以更改pure函数的返回类型,以隐式将其转换为immutableshared。这是有效的,因为在这些情况下,编译器知道返回的是一个新的唯一对象,并且将其转换为immutableshared不会违反类型系统。并非所有pure函数都符合条件,因为参数类型可以影响编译器是否可以保证返回值是唯一的,但是许多pure函数能够利用这一点并隐式地将它们的返回值转换为immutableshared。这很有用,因为它可以避免代码重复(针对不同的返回类型)或复制 - 因为如果返回的类型与immutableshared所需的类型不匹配,那么你可以'保证它不会在别处引用,你必须复制它以获得你想要的类型。在这种情况下,编译器能够保证对象不会在其他地方被引用,因此它可以安全地为您投射。

构造函数有效地返回新值,因此它们可能受此功能的影响。这使得如果构造函数是pure,您通常可以从中构造immutableshared值,而不必复制构造函数(就像它不是必须要做的那样) 't pure)。与其他pure函数一样,这是否有效取决于构造函数的参数类型,但它经常是可能的,它有助于避免代码重复。

导致问题的原因是当FixedList的构造函数都是pure时,编译器可以使用其中任何一个来构造shared对象。因此,它不知道选择哪一个,并给你一个模糊错误。

我已经将此作为bug报告了理论上编译器应该更喜欢显式标记为shared的构造函数,但是编译器开发人员会决定什么,我不知道。从pure函数隐式转换返回值的能力是一个相当新的特性,当我们能够而且不能做那些隐式转换时,仍在探索,这可能导致意外问题(比如这可能是)以及编译器错误(例如,至少有一个immutable的情况,当它不应该进行转换时)。我相信这些问题会很快得到解决。

答案 1 :(得分:2)

pure构造函数可以构建shared对象而不会将其标记为shared

显然,建构者推断出纯粹性。

writeln不是pure。因此,有了它,构造函数就不是pure

删除writeln后,构造函数将变为pure。两个构造函数现在都匹配shared调用。

相关问题