ref const(T) the same as C++'s const T&?

Jonathan M Davis jmdavisProg at gmx.com
Tue Feb 15 14:16:34 PST 2011


On Tuesday, February 15, 2011 12:35:31 Peter Alexander wrote:
> On 15/02/11 7:55 PM, Jonathan M Davis wrote:
> > On Tuesday, February 15, 2011 11:48:25 Peter Alexander wrote:
> >> Do D const references work the same as C++'s?
> >> 
> >> i.e.
> >> - Can they bind to rvalues?
> >> - Do they extend the life of rvalues?
> >> 
> >> If they do, are there any differences from C++?
> >> 
> >> If they don't, how do I pass large structs into a function efficiently?
> > 
> > The only bind to lvalues. A ref is a reference to a variable, so normal
> > ref has to be passed a variable. In C++, it was decided that const&  was
> > special and could take a temporary. In D, it's no different from ref
> > except that it's const, so it can't be changed. There have been requests
> > to fix this, but Andrei is adamant that it was a huge mistake in C++ to
> > do it since it makes it so that you can't determine whether a const&  is
> > really a rvalue or an lvalue. I don't know enough to know how much that
> > really matters, but apparently it causes problems. The result is that D
> > doesn't do that, which can be rather annoying when trying to pass
> > temporaries to functions which take const ref, but that's the way it
> > goes.
> > 
> > If you want to pass a large struct to a function efficiently, and you
> > know that function isn't going to need to alter the struct, make it
> > const ref. That way, it's const, and it doesn't get copied. However,
> > that means that you can't pass temporaries to it. However, if you need
> > to pass a temporary, then you're going to have to actually assign it to
> > a variable first.
> > 
> > I _thought_ tht you could define a cost ref version and a non-const ref
> > version and it would call the const ref version on lvalues and the
> > non-const ref version on rvalues, but when I just tried it, it seems to
> > call the non-const ref version in both cases. I don't know if that's a
> > bug or not. But if you just have a const ref version, and you create a
> > variable where you'd normally use a temporary, you'll be fine.
> > 
> > - Jonathan M Davis
> 
> Surely this is a major usability issue? I have to create a new local
> variable just so that I can pass structs round efficiently (either that
> or change the struct to have COW or ref semantics, both of which are
> unacceptable).

Well, if it's made so that you can have const ref and non-const ref version and 
the const ref gets called for lvalues and the non-const ref gets called for 
rvalues, then that fixes most of the problem, though it's still annoying. e.g.

int func(const ref S s)
{
   //...
}

int func(S s)
{
    return func(s);
}

At the moment, the const ref version only gets called if the struct you're 
passing in is actually const, so that idiom doesn't currently work. I'm not sure 
whether it's actually supposed to or not though. I would hope so, but I don't 
know.

Personally, it wouldn't hurt my feelings any to have const ref take temporaries. 
I do not understand why it's a problem. But Andrei insists that it is. 
Presumably Walter agrees, but I don't know. They could very well be right and 
that it's overall better _not_ to have const ref take temporaries, but it _is_ 
annoying. Since I don't understand what the real problem with not knowing 
whether const ref is actually referring to an lvalue or rvalue is, I can't 
really judge whether they're right or wrong. However, Andrei is certain that 
it's on of C++'s biggest mistakes.

Regardless, the general push has been that structs be cheap to copy, and I would 
argue that if you're structs _aren't_ relatively cheap to copy, you should at 
least consider rethinking your design. Sometimes COW or ref semantics will 
probably be required though.

There may be a way to solve this problem reasonably and still have const ref 
require lvalues, but for the moment, we have to deal with it.

- Jonathan M Davis


More information about the Digitalmars-d mailing list