Jump to page: 1 2
Thread overview
const references in C++ and D
May 30, 2010
bearophile
May 31, 2010
BCS
May 31, 2010
bearophile
May 31, 2010
BCS
May 31, 2010
bearophile
May 31, 2010
Trass3r
May 31, 2010
bearophile
May 31, 2010
Kagamin
May 31, 2010
bearophile
May 31, 2010
Kagamin
May 31, 2010
Trass3r
Jun 01, 2010
bearophile
Jun 03, 2010
Kagamin
Jun 03, 2010
Kagamin
Jun 03, 2010
bearophile
Jun 04, 2010
Kagamin
May 30, 2010
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?

Bye and thank you,
bearophile
May 31, 2010
Hello bearophile,

> 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.

Yes, by design, you can't have a reference to a temporary value.

> What is the
> right way to translate that C++ code to D2? (So far I have just
> commented out the 'ref' in opBinary).

Thats' what I'd do.

> 
> 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?
> 
> Bye and thank you,
> bearophile
-- 
... <IXOYE><



May 31, 2010
BCS:
> Thats' what I'd do.

But wasn't "auto ref" invented for such situations?

Bye and thank you,
bearophile
May 31, 2010
Hello bearophile,

> BCS:
> 
>> Thats' what I'd do.
>> 
> But wasn't "auto ref" invented for such situations?
> 

That would work too, assuming that the internals of the function allow it.

> Bye and thank you,
> bearophile
-- 
... <IXOYE><



May 31, 2010
BCS:
> That would work too, assuming that the internals of the function allow it.

I don't know what you mean (in that example 3 auto ref doesn't compile, I don't know if it's a compiler bug or if I am doing something wrong).

Bye and thank you,
bearophile
May 31, 2010
I think, it's a bug. It was denied to have write access to the temporary variable, but you request only read access which is safe to be provided.
May 31, 2010
Kagamin:

> I think, it's a bug. It was denied to have write access to the temporary variable, but you request only read access which is safe to be provided.<

Do you mean the program #3?

Thank you for your answers. For me sometimes it's not easy to tell apart my bugs from the compiler bugs.

Bye,
bearophile
May 31, 2010
bearophile Wrote:

> Kagamin:
> 
> > I think, it's a bug. It was denied to have write access to the temporary variable, but you request only read access which is safe to be provided.<
> 
> Do you mean the program #3?
I mean program #1

May 31, 2010
> I don't know what you mean (in that example 3 auto ref doesn't compile, I don't know if it's a compiler bug or if I am doing something wrong).

Looks like a compiler bug to me.
In which cases does it work/doesn't it work?
May 31, 2010
> I think, it's a bug. It was denied to have write access to the temporary variable, but you request only read access which is safe to be provided.

True, there should be an additional check if it's a const ref.
« First   ‹ Prev
1 2