【问题标题】:D: Const correctness - what am I doing wrong?D:常量正确性——我做错了什么?
【发布时间】:2014-02-11 05:50:36
【问题描述】:

我目前正在实现一个基于二叉树的数据结构。作为其中的一部分,我有(目前是公开的,以便于测试)实例变量leftright 作为用于创建我的结构的每个Node 对象的一部分。我希望能够快速访问的其中一件事是 sub,这是使用此功能完成的:

@property Node sub() 
    in {
        assert(!isLeaf);
    }
    body {
        return (val != left.val) ? left : right;
    }

这里所指的所有内容都是公开的。现在,我尝试在合约中使用这个属性函数(特别是out 块,函数绑定到result 的结果)。但是,当我这样做时,编译器抱怨说我正在使用 const result 对象调用可变方法。但是,当我将 sub 的签名更改为 @property const Node sub() 时,我得到了这个编译器错误:

Error: cannot implicitly convert expression (this.val != this.left.val ? this.left : this.right) of type const(Node) to tournament2.Node

我在这里缺少什么?我该如何解决这个问题?

【问题讨论】:

  • 尝试将签名更改为@property inout(Node) sub() inout
  • @Cyber​​Shadow:解决了,谢谢!你能向我描述一下为什么这行得通吗?我想了解我的问题的根源,这样我以后就不会绊倒了。

标签: properties constants d


【解决方案1】:

最初的问题源于合约不能修改它们所属的对象的限制(否则,程序在调试和发布模式下的行为可能会有所不同)。语言强制执行该限制的方式是使this 指针const

const this 表示不能修改this 对象的字段,至于调用方法——这些方法本身必须注解为const,同样的限制适用于这些方法的代码.这解释了第一个错误:合约,即const,试图调用非const(可变)方法。由于允许可变方法修改this,并且禁止合约这样做,因此编译器禁止调用。

由于 D 常量的传递性,通过this 指针访问的所有内容都变为const。而且,如果任何类字段是引用类型,它们的间接目标也将变为const。这就是类型系统禁止修改任何可以通过this 指针访问的内容的方式。

这意味着如果const 方法试图返回一个类字段(具有间接性,例如像Node 这样的类类型),则返回的类型也必须是const。这是第二条错误消息的来源:返回表达式试图将通过const this 获得的const Node 值转换为可变的Node。目前,语法@property const Node sub() 表示方法本身是const(并且具有const this),而不是返回类型。

现在,通常,在 C++ 中,具有适当 constness 支持的对象通常会对返回类字段的方法有多个重载:const 和非constconst 版本将返回 const 引用;非const 将返回非const 引用。当我们可以访问可变对象时,需要这两个版本来允许获取可变字段引用,但如果我们只有const 访问对象,仍然允许获取const 引用。大多数情况下,这两种方法的代码是相同的——只是函数签名不同。

这就是 D 的 inout 的用武之地。在方法和它的一些参数或返回值上指定它意味着这些参数或返回值将具有与 this 相同的常量(被引用的对象)。对于返回 const 和可变值使用相同代码的简单情况,这可以避免代码重复。

我使用的语法是@property inout(Node) sub() inout。我认为它可以用不止一种方式编写,但这种语法是明确的。这里,inout(Node) 中的括号明确表明我们将属性应用于返回值,而不是函数,并将方法 (this) inout 属性放在参数列表之后,就像 C++ 中的 const , 明确指定它适用于函数本身。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-29
    • 1970-01-01
    • 2012-04-15
    • 1970-01-01
    • 2020-10-01
    相关资源
    最近更新 更多