Community

main.d:
import std.stdio;
struct A
{
int member1;
}
struct B
{
int member2;
}
void main()
{
A a;
writefln( (cast(B)a).member2 );
}
That code results in the following compiletime errors:
main.d(16): Error: no property 'opCall' for type 'B'
main.d(16): Error: function expected before (), not 1 of type int
main.d(16): Error: no property 'member2' for type 'int'
I am using DMD 1.014 on Windows.
This seemed to work at some point in history, but not anymore. What am
I doing wrong?
Thanks

Chad J wrote:
> main.d:
> import std.stdio;
>
> struct A
> {
> int member1;
> }
>
> struct B
> {
> int member2;
> }
>
> void main()
> {
> A a;
> writefln( (cast(B)a).member2 );
> }
>
> That code results in the following compiletime errors:
> main.d(16): Error: no property 'opCall' for type 'B'
> main.d(16): Error: function expected before (), not 1 of type int
> main.d(16): Error: no property 'member2' for type 'int'
>
> I am using DMD 1.014 on Windows.
> This seemed to work at some point in history, but not anymore. What am
> I doing wrong?
>
> Thanks
Chad,
What you are doing there is illegal code. The structs A and B are
distinct types and cannot be cast to each other. If it worked in the
past, then it was probably a compiler bug.
Since structs do not allow for inheritance (they are value types), then
the only way would be to use classes and inheritance or templates.
What are you trying to achieve? Perhaps I can try to suggest a different
method.
Regards,
Myron.

Myron Alexander wrote:
> Chad J wrote:
>
>> main.d:
>> import std.stdio;
>>
>> struct A
>> {
>> int member1;
>> }
>>
>> struct B
>> {
>> int member2;
>> }
>>
>> void main()
>> {
>> A a;
>> writefln( (cast(B)a).member2 );
>> }
>>
>> That code results in the following compiletime errors:
>> main.d(16): Error: no property 'opCall' for type 'B'
>> main.d(16): Error: function expected before (), not 1 of type int
>> main.d(16): Error: no property 'member2' for type 'int'
>>
>> I am using DMD 1.014 on Windows.
>> This seemed to work at some point in history, but not anymore. What
>> am I doing wrong?
>>
>> Thanks
>
>
> Chad,
>
> What you are doing there is illegal code. The structs A and B are
> distinct types and cannot be cast to each other. If it worked in the
> past, then it was probably a compiler bug.
>
> Since structs do not allow for inheritance (they are value types), then
> the only way would be to use classes and inheritance or templates.
>
> What are you trying to achieve? Perhaps I can try to suggest a different
> method.
>
> Regards,
>
> Myron.
Ah, makes sense. I figured out what I was doing wrong in the original
code. Thanks.

Chad J wrote:
> Myron Alexander wrote:
>> Chad J wrote:
>>
>>> main.d:
>>> import std.stdio;
>>>
>>> struct A
>>> {
>>> int member1;
>>> }
>>>
>>> struct B
>>> {
>>> int member2;
>>> }
>>>
>>> void main()
>>> {
>>> A a;
>>> writefln( (cast(B)a).member2 );
>>> }
>>>
>>> That code results in the following compiletime errors:
>>> main.d(16): Error: no property 'opCall' for type 'B'
>>> main.d(16): Error: function expected before (), not 1 of type int
>>> main.d(16): Error: no property 'member2' for type 'int'
>>>
>>> I am using DMD 1.014 on Windows.
>>> This seemed to work at some point in history, but not anymore. What
>>> am I doing wrong?
>>>
>>> Thanks
>>
>>
>> Chad,
>>
>> What you are doing there is illegal code. The structs A and B are
>> distinct types and cannot be cast to each other. If it worked in the
>> past, then it was probably a compiler bug.
>>
>> Since structs do not allow for inheritance (they are value types),
>> then the only way would be to use classes and inheritance or templates.
>>
>> What are you trying to achieve? Perhaps I can try to suggest a
>> different method.
>>
>> Regards,
>>
>> Myron.
>
> Ah, makes sense. I figured out what I was doing wrong in the original
> code. Thanks.
This works:
void main()
{
A a;
writefln( (cast(B*)&a).member2 );
}
Just keep in mind that you can't take the address of a function
argument, so if you do this inside a function, you have to make a copy
first. I've used this trick to do all sorts of evil things like turn a
structure into a ubyte[] :P
-- Daniel
--
int getRandomNumber()
{
return 4; // chosen by fair dice roll.
// guaranteed to be random.
}
http://xkcd.com/
v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D
i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP http://hackerkey.com/

Daniel Keep wrote:
>
> Chad J wrote:
>
>>Myron Alexander wrote:
>>
>>>Chad J wrote:
>>>
>>>
>>>>main.d:
>>>>import std.stdio;
>>>>
>>>>struct A
>>>>{
>>>> int member1;
>>>>}
>>>>
>>>>struct B
>>>>{
>>>> int member2;
>>>>}
>>>>
>>>>void main()
>>>>{
>>>> A a;
>>>> writefln( (cast(B)a).member2 );
>>>>}
>>>>
>>>>That code results in the following compiletime errors:
>>>>main.d(16): Error: no property 'opCall' for type 'B'
>>>>main.d(16): Error: function expected before (), not 1 of type int
>>>>main.d(16): Error: no property 'member2' for type 'int'
>>>>
>>>>I am using DMD 1.014 on Windows.
>>>>This seemed to work at some point in history, but not anymore. What
>>>>am I doing wrong?
>>>>
>>>>Thanks
>>>
>>>
>>>Chad,
>>>
>>>What you are doing there is illegal code. The structs A and B are
>>>distinct types and cannot be cast to each other. If it worked in the
>>>past, then it was probably a compiler bug.
>>>
>>>Since structs do not allow for inheritance (they are value types),
>>>then the only way would be to use classes and inheritance or templates.
>>>
>>>What are you trying to achieve? Perhaps I can try to suggest a
>>>different method.
>>>
>>>Regards,
>>>
>>>Myron.
>>
>>Ah, makes sense. I figured out what I was doing wrong in the original
>>code. Thanks.
>
>
> This works:
>
> void main()
> {
> A a;
> writefln( (cast(B*)&a).member2 );
> }
>
> Just keep in mind that you can't take the address of a function
> argument, so if you do this inside a function, you have to make a copy
> first. I've used this trick to do all sorts of evil things like turn a
> structure into a ubyte[] :P
>
> -- Daniel
>
Yeah I like that trick. I didn't know about the copying function
arguments catch though, good to know.
I suppose I was also used to being able to cast structs into other
structs, sort of like how you can cast numeric types into other numeric
types, and generalizing it to being able to cast any value type into
another value type. Guess it doesn't hold though. I can always use
this dereference-address trick to get around it.

Daniel Keep wrote:
> Just keep in mind that you can't take the address of a function
> argument, so if you do this inside a function, you have to make a copy
> first.
I'm surprised by this statement, and can't find a mention of it in the spec.
Do you have a reference for it?

Frits van Bommel wrote:
> Daniel Keep wrote:
>> Just keep in mind that you can't take the address of a function
>> argument, so if you do this inside a function, you have to make a copy
>> first.
>
> I'm surprised by this statement, and can't find a mention of it in the
> spec.
> Do you have a reference for it?
I don't know if it's in the spec (I can't remember ever running across
it), but I know it doesn't work.
The problem is that the D calling convention allows for up to one
argument to be passed using registers, which don't *have* an address, so
taking the address of them doesn't always make sense.
In any case, I know the compiler has barfed every time I've tried to do
it...
-- Daniel
--
int getRandomNumber()
{
return 4; // chosen by fair dice roll.
// guaranteed to be random.
}
http://xkcd.com/
v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D
i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP http://hackerkey.com/

Daniel Keep wrote:
>
> Frits van Bommel wrote:
>> Daniel Keep wrote:
>>> Just keep in mind that you can't take the address of a function
>>> argument, so if you do this inside a function, you have to make a copy
>>> first.
>> I'm surprised by this statement, and can't find a mention of it in the
>> spec.
>> Do you have a reference for it?
>
> I don't know if it's in the spec (I can't remember ever running across
> it), but I know it doesn't work.
>
> The problem is that the D calling convention allows for up to one
> argument to be passed using registers, which don't *have* an address, so
> taking the address of them doesn't always make sense.
DMD automatically copies a register-argument to a local variable on the
stack if the address is required. As does my GDC, it seems...
> In any case, I know the compiler has barfed every time I've tried to do
> it...
It's always worked fine for me.
For instance, the following works, whether I'm using DMD or GDC:
---
import std.stdio;
void bar(int* x) {
assert(*x == 42);
writefln("*%s = %s", x, *x);
}
void foo(int x) {
bar(&x);
}
void main() {
foo(42);
}
---
(DMD 1.014, GDC 0.23/amd64)

Frits van Bommel wrote:
> Daniel Keep wrote:
>>
>> Frits van Bommel wrote:
>>> Daniel Keep wrote:
>>>> Just keep in mind that you can't take the address of a function
>>>> argument, so if you do this inside a function, you have to make a copy
>>>> first.
>>> I'm surprised by this statement, and can't find a mention of it in the
>>> spec.
>>> Do you have a reference for it?
>>
>> I don't know if it's in the spec (I can't remember ever running across
>> it), but I know it doesn't work.
>>
>> The problem is that the D calling convention allows for up to one
>> argument to be passed using registers, which don't *have* an address, so
>> taking the address of them doesn't always make sense.
>
> DMD automatically copies a register-argument to a local variable on the
> stack if the address is required. As does my GDC, it seems...
>
>> In any case, I know the compiler has barfed every time I've tried to do
>> it...
>
> It's always worked fine for me.
>
> For instance, the following works, whether I'm using DMD or GDC:
> ---
> import std.stdio;
>
> void bar(int* x) {
> assert(*x == 42);
> writefln("*%s = %s", x, *x);
> }
>
> void foo(int x) {
> bar(&x);
> }
>
> void main() {
> foo(42);
> }
> ---
> (DMD 1.014, GDC 0.23/amd64)
Weird; you're right. It does work. I *swear* it didn't used to, tho.
I remember having to work around the problem for a library I was writing
and being a bit annoyed at the time...
Oh well.
-- Daniel
--
int getRandomNumber()
{
return 4; // chosen by fair dice roll.
// guaranteed to be random.
}
http://xkcd.com/
v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D
i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP http://hackerkey.com/

"Daniel Keep" <daniel.keep.lists@gmail.com> wrote in message
news:f1hkrr$o19$1@digitalmars.com...
>
> Weird; you're right. It does work. I *swear* it didn't used to, tho.
> I remember having to work around the problem for a library I was writing
> and being a bit annoyed at the time...
>
> Oh well.
Sure you weren't trying to return the address of a parameter at the time?