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;
}
//生成复制构造器失败,因此不可复制它的实例

依赖项移除析构器会使其编译.
添加按引用取DependeropAssign也可工作:

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正确生成更准确的复制构造器会修复此问题.
另一个方法是停止基于复制构造器和析构器生成赋值操作符.

posted @   zjh6  阅读(12)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示