digitalmars.D - ref const(T) the same as C++'s const T&?
- Peter Alexander (7/7) Feb 15 2011 Do D const references work the same as C++'s?
- Jonathan M Davis (23/32) Feb 15 2011 The only bind to lvalues. A ref is a reference to a variable, so normal ...
- Peter Alexander (5/37) Feb 15 2011 Surely this is a major usability issue? I have to create a new local
- Jonathan M Davis (31/75) Feb 15 2011 Well, if it's made so that you can have const ref and non-const ref vers...
- Lutger Blijdestijn (6/25) Feb 15 2011 For reference, here is a link to the thread discussing it: http://www.ma...
- Peter Alexander (4/8) Feb 15 2011 Thanks Lutger.
- Lutger Blijdestijn (2/14) Feb 15 2011 Yes, I think so.
- Trass3r (15/16) Mar 01 2011 The weird thing is struct literals count as lvalues in D2, so this works...
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? Thanks
Feb 15 2011
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
Feb 15 2011
On 15/02/11 7:55 PM, Jonathan M Davis wrote:On Tuesday, February 15, 2011 11:48:25 Peter Alexander wrote: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).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
Feb 15 2011
On Tuesday, February 15, 2011 12:35:31 Peter Alexander wrote:On 15/02/11 7:55 PM, Jonathan M Davis wrote: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 DavisOn Tuesday, February 15, 2011 11:48:25 Peter Alexander wrote: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).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
Feb 15 2011
Jonathan M Davis wrote: ...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 DavisFor reference, here is a link to the thread discussing it: http://www.mail- archive.com/digitalmars-d puremagic.com/msg44075.html If I understood that discussion correctly, 'auto ref' is supposed to solve the rvalue references problem but are not completely implemented yet.
Feb 15 2011
On 15/02/11 10:47 PM, Lutger Blijdestijn wrote:For reference, here is a link to the thread discussing it: http://www.mail- archive.com/digitalmars-d puremagic.com/msg44075.html If I understood that discussion correctly, 'auto ref' is supposed to solve the rvalue references problem but are not completely implemented yet.Thanks Lutger. From the thread, it seems like the correct annotation would be 'auto ref const T', would it not?
Feb 15 2011
Peter Alexander wrote:On 15/02/11 10:47 PM, Lutger Blijdestijn wrote:Yes, I think so.For reference, here is a link to the thread discussing it: http://www.mail- archive.com/digitalmars-d puremagic.com/msg44075.html If I understood that discussion correctly, 'auto ref' is supposed to solve the rvalue references problem but are not completely implemented yet.Thanks Lutger. From the thread, it seems like the correct annotation would be 'auto ref const T', would it not?
Feb 15 2011
Peter Alexander Wrote:If they don't, how do I pass large structs into a function efficiently?The weird thing is struct literals count as lvalues in D2, so this works: struct A {} void foo(ref A a) {} void main() { foo(A()); } while calling the following doesn't: static A bar() { return A(); } foo(bar()); Where's the freaking difference?
Mar 01 2011