www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - no property 'opCall' for type ... what am I doing wrong?

reply Chad J <gamerChad _spamIsBad_gmail.com> writes:
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
May 04 2007
parent reply Myron Alexander <dprogramming myronRMVETHISalexander.com> writes:
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.
May 04 2007
parent reply Chad J <gamerChad _spamIsBad_gmail.com> writes:
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.
May 04 2007
parent reply Daniel Keep <daniel.keep.lists gmail.com> writes:
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/
May 04 2007
next sibling parent Chad J <gamerChad _spamIsBad_gmail.com> writes:
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.
May 04 2007
prev sibling parent reply Frits van Bommel <fvbommel REMwOVExCAPSs.nl> writes:
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?
May 05 2007
parent reply Daniel Keep <daniel.keep.lists gmail.com> writes:
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/
May 05 2007
parent reply Frits van Bommel <fvbommel REMwOVExCAPSs.nl> writes:
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.

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)
May 05 2007
parent reply Daniel Keep <daniel.keep.lists gmail.com> writes:
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.

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/
May 05 2007
parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"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?
May 05 2007
parent Daniel Keep <daniel.keep.lists gmail.com> writes:
Jarrett Billingsley wrote:
 "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?

I was trying to do one of two things: I was either trying to cast an inout argument into a ubyte[] or back, or trying to take the address of an argument, convert it to a ubyte[], then return a .dup of it. Basically, I was trying to do blind byte copies. -- 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/
May 05 2007