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);}
  • 对于#2(扩展为#3):不,这将是无效的,因为它必须是对刚刚超出范围的对象的引用。

    \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)
    。更多(谢谢你的链接)