www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Taking the address of an rvalue struct

reply dsimcha <dsimcha yahoo.com> writes:
The following code uses the this reference in a struct member function to take
the address of an rvalue struct.  Is it well-defined behavior equivalent to
taking the address of a named stack-allocated struct, or is the compiler free
to break it in optimized mode?

struct SomeStruct {
    int num;

    this(int x) {
       num = x;
    }

    SomeStruct* addressOf()  property {
        return &this;
    }
}

void main() {
   auto ptr = SomeStruct(42).addressOf;
   writeln(ptr.num);
}
Jul 22 2011
next sibling parent Cristi Cobzarenco <cristi.cobzarenco gmail.com> writes:
This is actually a question that has arisen in my GSoC problem, thanks
for asking David. In this case I'm pretty sure it would break if one
allocated something else on the stack. The case I'm more interested in
is something like this:

struct Sum {
   Value *a, *b;

   int eval() { return *a + *b; }
}

struct Value {
    int v;
    Value* addressOf()  property { return &this; }
}

void main() {
    writeln( Sum( Value(10).addressOf, Value(20).addressOf ).eval() );
}

To me it seems that as long as all the literals are allocated in the
same expression this should work, right?
}

---
Cristi Cobzarenco
BSc in Artificial Intelligence and Computer Science
University of Edinburgh
Profile: http://www.google.com/profiles/cristi.cobzarenco



On 22 July 2011 17:22, dsimcha <dsimcha yahoo.com> wrote:
 The following code uses the this reference in a struct member function to=
take
 the address of an rvalue struct. =A0Is it well-defined behavior equivalen=
t to
 taking the address of a named stack-allocated struct, or is the compiler =
free
 to break it in optimized mode?

 struct SomeStruct {
 =A0 =A0int num;

 =A0 =A0this(int x) {
 =A0 =A0 =A0 num =3D x;
 =A0 =A0}

 =A0 =A0SomeStruct* addressOf()  property {
 =A0 =A0 =A0 =A0return &this;
 =A0 =A0}
 }

 void main() {
 =A0 auto ptr =3D SomeStruct(42).addressOf;
 =A0 writeln(ptr.num);
 }
Jul 22 2011
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 7/22/11 10:22 AM, dsimcha wrote:
 The following code uses the this reference in a struct member function to take
 the address of an rvalue struct.  Is it well-defined behavior equivalent to
 taking the address of a named stack-allocated struct, or is the compiler free
 to break it in optimized mode?

 struct SomeStruct {
      int num;

      this(int x) {
         num = x;
      }

      SomeStruct* addressOf()  property {
          return&this;
      }
 }

 void main() {
     auto ptr = SomeStruct(42).addressOf;
     writeln(ptr.num);
 }
This has long been a feature that I attempted to remove several times. It steps from the fact that you can invoke methods on rvalue structs. Disallowing that would solve the issue, but would also eliminate a lot of convenience. Andrei
Jul 22 2011
parent reply dsimcha <dsimcha yahoo.com> writes:
== Quote from Andrei Alexandrescu (SeeWebsiteForEmail erdani.org)'s article
 This has long been a feature that I attempted to remove several times.
What? Taking the address of this? Invoking methods on rvalue structs?
 It steps from the fact that you can invoke methods on rvalue structs.
 Disallowing that would solve the issue, but would also eliminate a lot
 of convenience.
I think invoking methods on rvalue structs needs to be allowed come Hell or high water. What's wrong with just banning any optimization of rvalue structs that have methods called on them, i.e. requiring the compiler to treat them the same as named methods, allocate stack space for them that doesn't get reused elsewhere in the same function, etc.?
Jul 22 2011
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 7/22/11 12:10 PM, dsimcha wrote:
 == Quote from Andrei Alexandrescu (SeeWebsiteForEmail erdani.org)'s article
 This has long been a feature that I attempted to remove several times.
What? Taking the address of this? Invoking methods on rvalue structs?
The latter.
 It steps from the fact that you can invoke methods on rvalue structs.
 Disallowing that would solve the issue, but would also eliminate a lot
 of convenience.
I think invoking methods on rvalue structs needs to be allowed come Hell or high water. What's wrong with just banning any optimization of rvalue structs that have methods called on them, i.e. requiring the compiler to treat them the same as named methods, allocate stack space for them that doesn't get reused elsewhere in the same function, etc.?
Prolonging the lifetime of temporaries to the end of the enclosing function would be interesting, but perhaps surprising. Not to mention inefficient. Andrei
Jul 22 2011
next sibling parent Cristi Cobzarenco <cristi.cobzarenco gmail.com> writes:
I don't think it's neccessary to prolong their life till the end of
the scope, but as it stands their lifetime has to be at least as long
as the expression their in. I think that we should only disallow
non-const method calls, const methods conceptually make sense on
literals. Also disallowing method calls would conceivably also mean
disallowing operator overloads to work and one would not be able to
write stuff like Complex!double(-1.0,1.0) * z - which would be very
inconvenient.


---
Cristi Cobzarenco
BSc in Artificial Intelligence and Computer Science
University of Edinburgh
Profile: http://www.google.com/profiles/cristi.cobzarenco



On 22 July 2011 19:26, Andrei Alexandrescu
<SeeWebsiteForEmail erdani.org> wrote:
 On 7/22/11 12:10 PM, dsimcha wrote:
 =3D=3D Quote from Andrei Alexandrescu (SeeWebsiteForEmail erdani.org)'s
 article
 This has long been a feature that I attempted to remove several times.
What? =A0Taking the address of this? =A0Invoking methods on rvalue struc=
ts?
 The latter.

 It steps from the fact that you can invoke methods on rvalue structs.
 Disallowing that would solve the issue, but would also eliminate a lot
 of convenience.
I think invoking methods on rvalue structs needs to be allowed come Hell or high water. =A0What's wrong with just banning any optimization of rvalue stru=
cts
 that
 have methods called on them, i.e. requiring the compiler to treat them t=
he
 same as
 named methods, allocate stack space for them that doesn't get reused
 elsewhere in
 the same function, etc.?
Prolonging the lifetime of temporaries to the end of the enclosing functi=
on
 would be interesting, but perhaps surprising. Not to mention inefficient.


 Andrei
Jul 22 2011
prev sibling next sibling parent reply Peter Alexander <peter.alexander.au gmail.com> writes:
On 22/07/11 6:26 PM, Andrei Alexandrescu wrote:
 On 7/22/11 12:10 PM, dsimcha wrote:
 == Quote from Andrei Alexandrescu (SeeWebsiteForEmail erdani.org)'s
 article
 This has long been a feature that I attempted to remove several times.
What? Taking the address of this? Invoking methods on rvalue structs?
The latter.
How would you stop it though without totally crippling the language? e.g. if I have a struct Vec3, I would expect to be able to do: Vec3 a = Vec3(1, 0, 0) + Vec3(0, 1, 0); How would you accomplish that without calling Vec3.opBinary!"+" on an rvalue Vec3?
Jul 22 2011
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 7/22/11 1:30 PM, Peter Alexander wrote:
 On 22/07/11 6:26 PM, Andrei Alexandrescu wrote:
 On 7/22/11 12:10 PM, dsimcha wrote:
 == Quote from Andrei Alexandrescu (SeeWebsiteForEmail erdani.org)'s
 article
 This has long been a feature that I attempted to remove several times.
What? Taking the address of this? Invoking methods on rvalue structs?
The latter.
How would you stop it though without totally crippling the language?
That's why the feature hasn't been removed. Nevertheless, it's an awkward part of the language. Andrei
Jul 22 2011
prev sibling parent dsimcha <dsimcha yahoo.com> writes:
== Quote from Andrei Alexandrescu (SeeWebsiteForEmail erdani.org)'s

 I think invoking methods on rvalue structs needs to be allowed come Hell or
high
 water.  What's wrong with just banning any optimization of rvalue structs that
 have methods called on them, i.e. requiring the compiler to treat them the
same as
 named methods, allocate stack space for them that doesn't get reused elsewhere
in
 the same function, etc.?
Prolonging the lifetime of temporaries to the end of the enclosing function would be interesting, but perhaps surprising. Not to mention inefficient.
Well, it's slightly mitigated by only needing to prolong to the end of the enclosing scope. That said, I forgot about the extent to which destructors complicate things. I was thinking that the worst that happens by prolonging the lifetime is you waste a little extra stack space. If it weren't for the desire to avoid ridiculously complicated rules with exception after exception, I'd say that the lifetime should be prolonged iff there's no d'tor. That said, I still think that calling methods on rvalues needs to be preserved come Hell or high water. I'd rather have the weird corner cases happen when someone takes the address of a this reference (relatively uncommon) than when someone tries to, e.g. add two rvalue BigInts (common). For example: auto num = BigInt(2) + BigInt(3); The bottom line here is that there is no non-surprising behavior, at least that I can think of. Disallowing rvalue method calls will surprise a lot of ppl w.r.t. operator overloading. Prolonging lifetimes will surprise a lot of ppl w.r.t. when d'tors get called. The status quo will surprise a lot of ppl w.r.t. undefined behavior when they take the address of the this reference on an rvalue.
Jul 22 2011