D中的常数ref和右值
代码 编译错误D中的常数ref和右值,d,ref,rvalue,D,Ref,Rvalue,代码 编译错误 struct CustomReal { private real value; this(real value) { this.value = value; } CustomReal opBinary(string op)(CustomReal rhs) if (op == "+") { return CustomReal(value + rhs.value); } bool opEquals(ref
struct CustomReal
{
private real value;
this(real value)
{
this.value = value;
}
CustomReal opBinary(string op)(CustomReal rhs) if (op == "+")
{
return CustomReal(value + rhs.value);
}
bool opEquals(ref const CustomReal x) const
{
return value == x.value; // just for fun
}
}
// Returns rvalue
CustomReal Create()
{
return CustomReal(123.123456);
}
void main()
{
CustomReal a = Create();
assert(a == CustomReal(123.123456)); // OK. CustomReal is temporary but lvalue
assert(a == Create()); // Compilation error (can't bind to rvalue)
assert(a != a + a); // Compilation error (can't bind to rvalue)
}
问题:
const ref
无法绑定到右值?可以吗opBinary()
返回ref CustomReal
或const ref CustomReal
来修复此问题?可以吗ref CustomReal Create(){return CustomReal(0.0);}
\1
:是的,const ref不能绑定到右值。安德列认为在C++ Irc中允许这样做是不好的。
奇怪的是,在D2中,结构文字被算作左值,所以这是可行的:
prog.d(31): Error: function prog.CustomReal.opEquals (ref const const(CustomReal) x) const is not callable using argument types (CustomReal)
prog.d(31): Error: Create() is not an lvalue
调用以下命令时,不会:
struct A {}
void foo(ref A a) {}
void main()
{
foo(A());
}
ref
和const-ref
之间的唯一区别是const-ref
是const
而ref
不是。两者都必须接受一个变量。两者都不能采取临时措施。这与C++不同,其中代码> const t/< /c>将采用任何类型的值<代码> t>代码>包括临时值。
opBinary
无法返回ref
或const ref
,因为没有可返回的变量。它正在创建一个临时的。这同样适用于Create
。创建一个具有您想要返回的值的局部变量也没有帮助,因为您不能返回对局部变量的引用。它最终会引用一个不再存在的变量
这里需要做的是添加另一个超负荷的opEquals
:
static A bar()
{
return A();
}
foo(bar());
这样,您的代码就可以编译了
不过,我要指出的是,opEquals
目前的状况确实需要稍微解决一下。您会注意到,如果您只有我提供给您的opEquals
的重载,而不是您当前拥有的重载,那么代码无法编译,并且您会得到类似于以下内容的错误:
bool opEquals(CustomReal x) const
{
return value == x.value; // just for fun
}
编译器目前对结构的opEquals
的确切签名过于挑剔(其他一些函数,如toString
,也有类似的问题)。这是一个已知的问题,可能会在不久的将来得到解决。但是,现在,只需声明opEquals
的两个重载即可。如果将CustomReal
与变量进行比较,则将使用const ref
版本,如果将CustomReal
与临时版本进行比较,则将使用其他版本。但如果你两者都有,你应该没事
现在,为什么
prog.d(15): Error: function prog.CustomReal.opEquals type signature should be const bool(ref const(CustomReal)) not const bool(CustomReal x)
assert(a == Create());
工作,以及
assert(a == CustomReal(123.123456));
assert(a == CustomReal(123.123456));
没有,我不确定。考虑到const-ref
不能接受一个临时值,但出于某种原因,编译器在这里接受它——这可能与它如何对待opEquals
特殊值有关。不管怎样,正如我所说的,opEquals
和结构有一些问题需要解决,希望这很快就会发生。但与此同时,宣布opEquals
的两个重载似乎都起到了作用
编辑:似乎
工作,以及
assert(a == CustomReal(123.123456));
assert(a == CustomReal(123.123456));
这不是因为(出于我不理解的原因)结构文本被认为是左值,而不是
ref
的函数的返回值(毫不奇怪)是右值。有很多与之相关的观点,认为结构文本应该是右值,但显然它们是设计上的左值(这让我感到困惑)。在任何情况下,这就是为什么接受const-ref
的函数使用结构文本,而不使用函数的返回值。如果在中使用而不是ref-const
编译器告诉我opEquals()
应该使用ref-const
,会发生什么情况。我重载了opEquals(),但是编译器告诉我一个函数参数与两个opEquals()都匹配,所以它不能被编译。看见问题似乎在于CustomReal(123.123456)
临时对象未被视为右值。我不明白为什么。ideone版本的dmd已经过时了。他们用的是2.042。最新的是2.054。只要它的dmd版本是那么旧,你就不能相信ideone会编译什么和不会编译什么。它落后了12个版本。我在2.053家用mac上测试了它,但失败了。我刚刚更新到2.054,它似乎在工作。谢谢不管怎么说,这只虫子很新鲜。它可能是。正如我所说的,opEquals
和structs的问题仍然需要进行一些整理(),因此很有可能在整理好之后情况会再次发生变化。D、 作为一种语言,在这一点上是相当稳定的,但是在必要时会进行一些调整来解决类似的问题,并且由于编译器上的bug已经修复,行为有时会发生变化(通常是为了更好)。因此,虽然情况趋于稳定,但仍有一些变化,使用最新的编译器对某些事情来说确实很重要。因为你在Mac上,我要警告你,尽管dmd的当前版本(以及所有IIUC版本)在新的Mac OS X版本Lion(和)上不能正常工作。它应该在下一个版本中修复,但是由于Lion中的新ASLR,您可能会有内存问题。您还记得他的论点吗?或者你有一个链接?对链接使用标记,如[可见文本](url)
。更多(谢谢你的链接)