d无法生成复制构造器
原文
Digger抱怨是复制构造器的原因.
是的;它适合postblit和按值复制的构造器,但不适合按引用使用的复制构造器.
化简用例:
struct Array
{
void opSliceAssign(Foo) {}
void opSliceAssign(Foo, size_t, size_t) {}
}
struct Foo {
Bar _bar;
}
struct Bar {
version (Bug)
this(ref Bar) { }
else
this(Bar) { }
}
void main()
{
Foo foo;
Array arr;
arr[] = foo;
}
基本问题是,编译器看到有个定义了复制构造器的字段的构时,会生成如下形式的inout复制构造器:
this(ref inout(T)) inout;
此时,它为Foo创建如下复制构造器:
this(ref inout(Foo) p) inout
{
this._bar = p._bar;
}
因为,
this._bar = p._bar
//重写为
this._bar.__copyCtor(p._bar)
因为不能用'(ref inout(Bar))inout'参数类型调用'this(ref Bar)',生成的复制构造器编译失败.因此按disable注解它.
我实现复制构造器时,最初提出该方案时考虑到,如果想升级postblits为复制构造器,那么可简单地替换
this(this)
//为
this(ref inout typeof(this) p) inout
这样,postblit的生成机制会类似,且代码不会受到影响.
然而,我想了又想,想到了更好生成方案.它可消除该错误且代码可编译,但是Walter反对,所以现在被inout构造器卡住了.
所以,总结一下,按目前语言规则,该错误是正确的.
修复方法是用'inout'如下注解Bar的复制构造器:
this(ref inout(Bar)) inout
这使代码编译.但我同意可改进该错误的.
如果结构包含间接指针,这就不管用了,如,添加可变指针到Bar.
谢谢你的解释,这真需要一些工作.目前,如下都失败了
struct Bar { this(ref Bar) {} }
struct Bar { this(const ref Bar) {} }
因为编译器为
struct Foo { Bar _bar; }
生成inout复制构造器
如果失败了,不应完全禁止它,而应该试回退到可变或常的复制构造器,并传播字段的限制.
原文
如果字段定义了复制构造器,则无法生成并调用复制构造器.
这对使用引用计数的类型是相当令人沮丧的.
void main() {
Depender a, b;
b = a;
}
struct Dependency {
this(ref Dependency other) {
this.tupleof = other.tupleof;
}
~this() {
}
}
struct Depender {
Dependency dependency;
}
//生成复制构造器失败,因此不可复制它的实例
从依赖项中移除析构器会使其编译.
添加按引用取Depender的opAssign也可工作:
void opAssign(ref Depender other) {
this.tupleof = other.tupleof;
}
生成Depender的复制构造器时,如下:
this(ref inout Depender src) inout
{
this.dependency = dependency;
}
但是,
this.dependency = dependency;
//重写为,不能调用的
this.dependency.copyCtor(dependency);
因为它是可变的,而用inout对象,所以不能调用它.因此,按disable标记复制构造器.
Dependency的析构器使编译器生成带:
ref Dependency opAssign(Dependency src)
签名的opAssign.该赋值操作符使(包含Dependency的)Depender也定义了按值接收参数的opAssign.在此调用生成(和禁止)的复制构造器.
修复20876以正确生成更准确的复制构造器会修复此问题.
另一个方法是停止基于复制构造器和析构器生成赋值操作符.
浙公网安备 33010602011771号