May 31, 2010 Re: const references in C++ and D | ||||
---|---|---|---|---|
| ||||
Posted in reply to Trass3r | Trass3r:
> In which cases does it work/doesn't it work?
This doesn't work, I have shown the given error messages in the original post:
//#3
struct Vec {
Vec opOpAssign(string Op)(auto ref Vec other) if (Op == "+=") {
return this;
}
Vec opBinary(string Op:"+")(Vec other) {
Vec result;
return result += other;
}
}
void main() {
Vec v;
v += Vec() + Vec(); // line 13
}
It works if you remove "auto ref". I think this is a compiler bug. I will put it in bugzilla. The program #1 and 2# are instead correct according to D specs.
Bye,
bearophile
|
June 01, 2010 Re: const references in C++ and D | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | On Sun, 30 May 2010 19:03:57 -0400, bearophile <bearophileHUGS@lycos.com> wrote:
> I am translating a small C++ program to D2 and I am having problems. I am learning, but my mind is not large enough for all the subtleties of both C++ and D2 yet :-)
>
> This C++ program compiles:
>
>
> struct Vec {
> void operator+(const Vec& other) {}
> };
> Vec bar(Vec x) {
> return x;
> }
> int main() {
> Vec() + bar(Vec());
> }
>
>
>
> I think this is the equivalent D2 program:
>
> // program #1
> struct Vec {
> void opBinary(string Op:"+")(const ref Vec other) {}
> }
> Vec bar(Vec x) {
> return x;
> }
> void main() {
> Vec() + bar(Vec()); // line 9
> }
>
>
> But DMD gives me:
> temp3.d(9): Error: function temp3.Vec.opBinary!("+").opBinary (ref const const(Vec) other) is not callable using argument types (Vec)
> temp3.d(9): Error: bar((Vec())) is not an lvalue
>
>
> I vaguely remember a discussion about this in the D newsgroup, that D acts like this on purpose, so I think this is not a D bug. What is the right way to translate that C++ code to D2? (So far I have just commented out the 'ref' in opBinary).
>
>
> Another case, to me it seems the same problem (D2 code):
>
>
> // program #2
> struct Vec {
> Vec opOpAssign(string Op:"+=")(ref Vec other) {
> return this;
> }
> Vec opBinary(string Op:"*")(int k) {
> return this;
> }
> }
> void main() {
> Vec x;
> x += Vec() * 2; // line 12
> }
>
>
> DMD prints:
> temp3.d(12): Error: function temp3.Vec.opOpAssign!("+=").opOpAssign (ref Vec other) is not callable using argument types (Vec)
> temp3.d(12): Error: (Vec()).opBinary(2) is not an lvalue
>
> Again I have just commented out the 'ref' here and in most other operator overloading methods.
>
>
> I have seen that in some cases I can use "auto ref" (like in those two examples), but not in all of them, I don't know why. For example here:
>
>
> // program #3
> struct Vec {
> Vec opOpAssign(string Op)(auto ref Vec other) if (Op == "+=") {
> return this;
> }
> Vec opBinary(string Op:"+")(Vec other) {
> Vec result;
> return result += other;
> }
> }
> void main() {
> Vec v;
> v += Vec() + Vec(); // line 13
> }
>
>
> DMD prints:
> temp3.d(13): Error: function temp3.Vec.opOpAssign!("+=").opOpAssign (auto ref Vec other) is not callable using argument types (Vec)
> temp3.d(13): Error: (Vec()).opBinary((Vec())) is not an lvalue
>
> Do you know why "auto ref" isn't right here?
I've had a long private discussion with Andrei about this problem. C++ allows rvalues to be passed into functions that accept const ref. However, it surprisingly is less optimal for rvalues to pass by ref. The reason is because, you must put the temporary on the stack, and then also put the reference on the stack. By simply passing the struct without ref, it's not copied as an lvalue would be, it's simply used where it is, because the compiler knows that it's no longer needed in the calling function. So the optimizer can work more efficiently to remove those extra pushes and pops.
In C++, the optimial solution would be to allow the following duplicated methods:
foo(const ref Vec);
foo(const Vec);
as overloads, with the compiler choosing the first for lvalues and the second for rvalues. But you cannot overload based on ref, so this is not allowed.
D's solution is to use auto ref, but I think your attempts to use it show that it doesn't work. You should file a bug with your program 3.
-Steve
|
June 01, 2010 Re: const references in C++ and D | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | Steven Schveighoffer: > D's solution is to use auto ref, but I think your attempts to use it show that it doesn't work. You should file a bug with your program 3. Thank you for your always useful explanations, Steven (this is a fragile bug report, if you change the code a bit the bug vanishes). http://d.puremagic.com/issues/show_bug.cgi?id=4258 Bye, bearophile |
June 03, 2010 Re: const references in C++ and D | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | Steven Schveighoffer Wrote: > However, it surprisingly is less optimal for rvalues to pass by ref. So what? It just must work. Efficiency of a particular operation doesn't mean efficiency of a program: it can use lvalues most of time. > D's solution is to use auto ref, but I think your attempts to use it show that it doesn't work. You should file a bug with your program 3. auto ref works only for return values, implementing it for parameters means combinatorial bloat. |
June 03, 2010 Re: const references in C++ and D | ||||
---|---|---|---|---|
| ||||
Posted in reply to Kagamin | On Thu, 03 Jun 2010 09:09:39 -0400, Kagamin <spam@here.lot> wrote: > Steven Schveighoffer Wrote: > >> However, it surprisingly is less optimal for rvalues to pass by ref. > > So what? It just must work. Efficiency of a particular operation doesn't mean efficiency of a program: it can use lvalues most of time. Using lvalues is just as inefficient as passing temporaries via ref. The issue is that you can get *better* performance by passing temporaries by value than you can get by passing lvalues by value or by reference. Without something like auto ref, you put achieving the highest performance at odds with usability. > >> D's solution is to use auto ref, but I think your attempts to use it show >> that it doesn't work. You should file a bug with your program 3. > > auto ref works only for return values, implementing it for parameters means combinatorial bloat. At this point, the problem is that there is *nothing* that works for both rvalues and lvalues. auto ref would be something that works, even if it meant duplicating generated code. I personally don't see a huge problem with allowing temporaries to be passed via ref const. It could be a tradeoff between low performance vs. smaller footprint. But Andrei feels very strongly that passing temporaries via const ref is a complete mess in C++, so you'll have to convince him. -Steve |
June 03, 2010 Re: const references in C++ and D | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | Steven Schveighoffer Wrote:
> But Andrei feels very strongly that passing temporaries via const ref is a complete mess in C++, so you'll have to convince him.
If the issue is not performance, it shouldn't be mentioned from the start.
|
June 03, 2010 Re: const references in C++ and D | ||||
---|---|---|---|---|
| ||||
Posted in reply to Kagamin | On Thu, 03 Jun 2010 09:47:19 -0400, Kagamin <spam@here.lot> wrote:
> Steven Schveighoffer Wrote:
>
>> But Andrei feels very strongly that passing temporaries via const ref is a
>> complete mess in C++, so you'll have to convince him.
>
> If the issue is not performance, it shouldn't be mentioned from the start.
*My* issue is not performance. Andrei's is.
I just want something that works. Andrei doesn't want to add some feature that he thinks is a failure in C++.
I'm speaking too much for Andrei here, but I think this is the way he feels.
-Steve
|
June 03, 2010 Re: const references in C++ and D | ||||
---|---|---|---|---|
| ||||
Posted in reply to Kagamin | Kagamin:
> auto ref works only for return values,
In most cases seems to work with (input) arguments too.
Bye,
bearophile
|
June 04, 2010 Re: const references in C++ and D | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | bearophile Wrote:
> Kagamin:
> > auto ref works only for return values,
>
> In most cases seems to work with (input) arguments too.
>
I'm affraid, it works by ignoring auto attribute.
|
Copyright © 1999-2021 by the D Language Foundation