我在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位代码,但它仍然是相同的。我做错了什么,或者这是一个错误?
答案 0 :(得分:3)
pure
,nothrow
和@safe
是模板函数的推断。由于FixedList
是模板化的,因此它的构造函数是模板化的。 writeln
不是(也不可能)pure
,因为它是I / O.因此,虽然writeln
在构造函数中,但它们被推断为不是pure
,但构造函数正在执行的所有其他操作都是pure
,因此无需调用writeln
,他们成为pure
。
在某些情况下,编译器可以更改pure
函数的返回类型,以隐式将其转换为immutable
或shared
。这是有效的,因为在这些情况下,编译器知道返回的是一个新的唯一对象,并且将其转换为immutable
或shared
不会违反类型系统。并非所有pure
函数都符合条件,因为参数类型可以影响编译器是否可以保证返回值是唯一的,但是许多pure
函数能够利用这一点并隐式地将它们的返回值转换为immutable
或shared
。这很有用,因为它可以避免代码重复(针对不同的返回类型)或复制 - 因为如果返回的类型与immutable
或shared
所需的类型不匹配,那么你可以'保证它不会在别处引用,你必须复制它以获得你想要的类型。在这种情况下,编译器能够保证对象不会在其他地方被引用,因此它可以安全地为您投射。
构造函数有效地返回新值,因此它们可能受此功能的影响。这使得如果构造函数是pure
,您通常可以从中构造immutable
和shared
值,而不必复制构造函数(就像它不是必须要做的那样) 't pure
)。与其他pure
函数一样,这是否有效取决于构造函数的参数类型,但它经常是可能的,它有助于避免代码重复。
导致问题的原因是当FixedList
的构造函数都是pure
时,编译器可以使用其中任何一个来构造shared
对象。因此,它不知道选择哪一个,并给你一个模糊错误。
我已经将此作为bug报告了理论上编译器应该更喜欢显式标记为shared
的构造函数,但是编译器开发人员会决定什么,我不知道。从pure
函数隐式转换返回值的能力是一个相当新的特性,当我们能够而且不能做那些隐式转换时,仍在探索,这可能导致意外问题(比如这可能是)以及编译器错误(例如,至少有一个immutable
的情况,当它不应该进行转换时)。我相信这些问题会很快得到解决。
答案 1 :(得分:2)
pure
构造函数可以构建shared
对象而不会将其标记为shared
。
显然,建构者推断出纯粹性。
writeln
不是pure
。因此,有了它,构造函数就不是pure
。
删除writeln
后,构造函数将变为pure
。两个构造函数现在都匹配shared
调用。