[英]D: Const correctness - what am I doing wrong?
I am currently implementing a binary-tree-based data structure. 我目前正在实现基于二叉树的数据结构。 As part of that, I have (currently public, for easier testing) instance variables
left
and right
as part of each Node
object used in creating my structure. 作为其中的一部分,我有(目前公开,更容易测试)实例变量
left
和right
的各部分Node
创建我的结构中使用的对象。 One of the things I want to be able to access quickly is a sub, which is done using this function: 我希望能够快速访问的一件事是sub,使用此函数完成:
@property Node sub()
in {
assert(!isLeaf);
}
body {
return (val != left.val) ? left : right;
}
All of the stuff this refers to is public. 这指的所有内容都是公开的。 Now, I tried to use this property function in a contract (specifically the
out
block, with the result of the function binding to result
). 现在,我尝试在契约中使用此属性函数(特别是
out
块,其结果是函数绑定到result
)。 However, when I did this, the compiler complained that I'm calling a mutable method using the const result
object. 但是,当我这样做时,编译器抱怨我正在使用const
result
对象调用一个可变方法。 When I changed the signature of sub
to be @property const Node sub()
, however, I get this compiler error instead: 当我将
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
What am I missing here? 我在这里错过了什么? How can I resolve this?
我该如何解决这个问题?
The initial problem stems from the restriction that contracts cannot modify the object they belong to (otherwise, the program might behave differently in debug and release mode). 最初的问题源于合同无法修改其所属对象的限制(否则,程序在调试和发布模式下的行为可能会有所不同)。 The way the language enforces that restriction is by making the
this
pointer const
. 语言强制执行该限制的方式是使
this
指针成为const
。
A const this
means is that you can't modify the this
object's fields, and as for calling methods - those methods themselves must be annotated as const
, and the same restrictions apply to the code of those methods. const this
意味着你不能修改this
对象的字段,而对于调用方法 - 这些方法本身必须注释为const
,并且这些方法的代码也适用相同的限制。 This explains the first error: the contract, which was const
, was trying to call a non- const
(mutable) method. 这解释了第一个错误:合同,它是
const
,试图调用非const
(可变)方法。 Since mutable methods are allowed to modify this
, and contracts are forbidden to do so, the compiler forbids the call. 由于允许可变方法修改
this
,并且禁止合同这样做,编译器禁止调用。
Because of the transitive nature of D's constness, everything that's accessed through the this
pointer becomes const
. 由于D的
const
的传递性质,通过this
指针访问的所有内容都变为const
。 And, if any of the class fields are reference types, the target of their indirections becomes const
too. 并且,如果任何类字段是引用类型,则它们的间接目标也变为
const
。 This is how the type system will forbid modifying anything that can be reached through the this
pointer. 这就是类型系统将禁止修改通过
this
指针可以访问的任何内容的方式。
The implication of this is that if a const
method is trying to return a class field (with indirections, such as a class type like Node
), the returned type must also be const
. 这意味着如果
const
方法试图返回一个类字段(具有间接性,例如像Node
这样的类类型),则返回的类型也必须是const
。 This is the source of the second error message: the return expression attempted to convert the const Node
value, obtained through the const this
, to a mutable Node
. 这是第二条错误消息的来源:返回表达式试图将通过
const this
获得的const Node
值转换为可变Node
。 Currently, the syntax @property const Node sub()
indicates that the method itself is const
(and has as const this
), not the return type. 目前,语法
@property const Node sub()
表示方法本身是const
(并且具有const this
),而不是返回类型。
Now, generally, in C++, an object with proper constness support will usually have multiple overloads for the methods which return a class field: const
, and non- const
. 现在,通常,在C ++中,具有适当const支持的对象通常会为返回类字段的方法提供多个重载:
const
和non const
。 The const
versions will return a const
reference; const
版本将返回一个const
引用; the non- const
will return a non- const
reference. 非
const
将返回非const
引用。 The two versions are needed to allow obtaining a mutable field reference when we have access to a mutable object, but still allow getting a const
reference if we only have const
access to the object. 当我们访问可变对象时,需要两个版本来允许获取可变字段引用,但如果我们只有对该对象的
const
访问权限,则仍允许获取const
引用。 Most of the time, the code of the two methods will be identical - only the function signature will differ. 大多数情况下,两种方法的代码是相同的 - 只有函数签名才会有所不同。
This is where D's inout
comes in. Specifying it on the method and some of its arguments or return value means that those arguments or return value will have the same constness as that of this
(the object being referred to). 这是D的
inout
用武之地。在方法以及它的一些参数或返回值指定这意味着这些参数或返回值将具有相同的常量性作为的this
(对象被称为)。 This avoids code duplication for the simple cases where returning const
and mutable values uses the same code. 这避免了返回
const
和mutable值使用相同代码的简单情况下的代码重复。
The syntax I used is @property inout(Node) sub() inout
. 我使用的语法是
@property inout(Node) sub() inout
。 I think it can be written in more than one way, but this syntax is unambiguous. 我认为它可以用多种方式编写,但这种语法是明确的。 Here, the parens in
inout(Node)
make it explicit that we apply the attribute on the return value, and not the function, and placing the method ( this
) inout
attribute after the parameter list, like const
in C++, unambigously specifies that it applies to the function itself. 这里,
inout(Node)
的parens明确表示我们将属性应用于返回值,而不是函数,并将参数列表之后的方法( this
)放在inout
属性中,就像C ++中的const
一样,明确指定它适用于函数本身。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.