www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Pointer to member variable again

reply ws <wisiong gmail.com> writes:
Suppose i have the following:

int function() fp;
int *ptr;
class Cls
{
 int k;
 int foo()  {  return 0;  }
}

void main()
{
 fp = &Cls.foo;

 Cls c = new Cls;
 ptr = &c.k;  // <-- why always need a new instance?
}

As compared to delegate, is there no analogous way to specify this?

ptr = &Cls.k

Thanks!
Jul 28 2008
next sibling parent reply Carl Clark <carlclark lavabit.com> writes:
Shouldn't this work?

//...
class Cls
{
   int k;
   static int foo() { return 0; }
}
//...

The deal is that int foo() by itself is an instance method, but static 
declares it a class method, which is what you want -- class methods are 
shared, so you can simply call (or dereference) them without instances.

On 2008-07-28 19:45, ws spoke thusly:
 Suppose i have the following:
 
 int function() fp;
 int *ptr;
 class Cls
 {
  int k;
  int foo()  {  return 0;  }
 }
 
 void main()
 {
  fp = &Cls.foo;
 
  Cls c = new Cls;
  ptr = &c.k;  // <-- why always need a new instance?
 }
 
 As compared to delegate, is there no analogous way to specify this?
 
 ptr = &Cls.k
 
 Thanks!

Jul 28 2008
next sibling parent reply ws <wisiong gmail.com> writes:
Maybe i should have written it this way:

int function() fp;
int delegate() dp;
int *ptr;
class Cls
{
  int k;
  int foo()  { return k; }
}

void main()
{
  fp = &Cls.foo;
  assert(fp() == 0);

  Cls c = new Cls;
  dp = &c.foo;
  ptr = &c.k;
	
  assert(is(typeof(ptr) == int*));
  assert(is(typeof(fp) == int function()));
  assert(is(typeof(dp) == int delegate()));
}

Notice fp can be used without an instance of Cls.
What i need is actually a way to get the type of the class when i reference the
variable k, without actually creating an instance of the class. 
Something like this:

typedef GetClass!(Cls.k) classType;
assert(is(typeof(classtype) == class) && is(typeof(classtype) == Cls));

Is there a way to do it?
Jul 28 2008
parent ws <wisiong gmail.com> writes:
Simen Kjaeraas Wrote:

 On Tue, 29 Jul 2008 07:33:51 +0200, ws <wisiong gmail.com> wrote:
 
 Maybe i should have written it this way:

 int function() fp;
 int delegate() dp;
 int *ptr;
 class Cls
 {
   int k;
   int foo()  { return k; }
 }

 void main()
 {
   fp = &Cls.foo;
   assert(fp() == 0);

   Cls c = new Cls;
   dp = &c.foo;
   ptr = &c.k;
 	
   assert(is(typeof(ptr) == int*));
   assert(is(typeof(fp) == int function()));
   assert(is(typeof(dp) == int delegate()));
 }

 Notice fp can be used without an instance of Cls.
 What i need is actually a way to get the type of the class when i  
 reference the variable k, without actually creating an instance of the  
 class.
 Something like this:

 typedef GetClass!(Cls.k) classType;
 assert(is(typeof(classtype) == class) && is(typeof(classtype) == Cls));

 Is there a way to do it?

Have you tried calling fp in that example? -- Simen

Sorry the fp has to be called after Cls is instanstiated. Fixed as below: fp = &Cls.foo; Cls c = new Cls; assert(fp() == 0); <-- after Cls instantiation.
Jul 29 2008
prev sibling next sibling parent "Simen Kjaeraas" <simen.kjaras gmail.com> writes:
On Tue, 29 Jul 2008 07:33:51 +0200, ws <wisiong gmail.com> wrote:

 Maybe i should have written it this way:

 int function() fp;
 int delegate() dp;
 int *ptr;
 class Cls
 {
   int k;
   int foo()  { return k; }
 }

 void main()
 {
   fp = &Cls.foo;
   assert(fp() == 0);

   Cls c = new Cls;
   dp = &c.foo;
   ptr = &c.k;
 	
   assert(is(typeof(ptr) == int*));
   assert(is(typeof(fp) == int function()));
   assert(is(typeof(dp) == int delegate()));
 }

 Notice fp can be used without an instance of Cls.
 What i need is actually a way to get the type of the class when i  
 reference the variable k, without actually creating an instance of the  
 class.
 Something like this:

 typedef GetClass!(Cls.k) classType;
 assert(is(typeof(classtype) == class) && is(typeof(classtype) == Cls));

 Is there a way to do it?

Have you tried calling fp in that example? -- Simen
Jul 29 2008
prev sibling parent "Koroskin Denis" <2korden gmail.com> writes:
On Wed, 30 Jul 2008 06:39:30 +0400, ws <wisiong gmail.com> wrote:

 Simen Kjaeraas Wrote:

 On Tue, 29 Jul 2008 07:33:51 +0200, ws <wisiong gmail.com> wrote:

 Maybe i should have written it this way:

 int function() fp;
 int delegate() dp;
 int *ptr;
 class Cls
 {
   int k;
   int foo()  { return k; }
 }

 void main()
 {
   fp = &Cls.foo;
   assert(fp() == 0);

   Cls c = new Cls;
   dp = &c.foo;
   ptr = &c.k;
 	
   assert(is(typeof(ptr) == int*));
   assert(is(typeof(fp) == int function()));
   assert(is(typeof(dp) == int delegate()));
 }

 Notice fp can be used without an instance of Cls.
 What i need is actually a way to get the type of the class when i
 reference the variable k, without actually creating an instance of the
 class.
 Something like this:

 typedef GetClass!(Cls.k) classType;
 assert(is(typeof(classtype) == class) && is(typeof(classtype) ==  

 Is there a way to do it?

Have you tried calling fp in that example? -- Simen

Sorry the fp has to be called after Cls is instanstiated. Fixed as below: fp = &Cls.foo; Cls c = new Cls; assert(fp() == 0); <-- after Cls instantiation.

No, that's wrong. Suppose you have two instances: Cls first = new Cls(); first.k = 1; Cls second = new Cls(); second.k = 2; int result = fp(); Question is what is the result of the fp() call? Lets do some renaming: class Human { char[] name; char[] getName() { return name; } } Human me = new Human(); me.name = "Denis" Human you = new Human(); you.name = "Rui"; char[] name = Human.getName(); // what's the result? char[] function() fp = &Human.getName(); char[] name2 = fp(); The answer is... none. The code is wrong. You can't access a property, which is different among class instances, like there is no such thing as common human name. Or age. Or anything else. There should be someone whose properties you are trying to determine - an object, class instance. char[] name1 = me.getName(); // returns "Denis" char[] name2 = you.getName(); // returns "Rui"
Jul 30 2008
prev sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"ws" wrote
 Suppose i have the following:

 int function() fp;
 int *ptr;
 class Cls
 {
 int k;
 int foo()  {  return 0;  }
 }

 void main()
 {
 fp = &Cls.foo;

 Cls c = new Cls;
 ptr = &c.k;  // <-- why always need a new instance?
 }

 As compared to delegate, is there no analogous way to specify this?

 ptr = &Cls.k

 Thanks!

In fact, this should fail to compile. The fact that it succeeds is a bug. You should enter it in bugzilla (is it already there?) Did you try running it? I get a segfault. fp is a member function, which means it needs a hidden 'this' pointer. When you assign &Cls.foo to fp, this should result in the same error as if you typed Cls.foo(): Error: need 'this' to access member foo -Steve
Jul 29 2008
next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"Steven Schveighoffer" wrote
 fp is a member function, which means it needs a hidden 'this' pointer.

Meant to write "foo is a member function..." Sorry, -STeve
Jul 29 2008
prev sibling parent reply Kirk McDonald <kirklin.mcdonald gmail.com> writes:
Steven Schveighoffer wrote:
 "ws" wrote
 
Suppose i have the following:

int function() fp;
int *ptr;
class Cls
{
int k;
int foo()  {  return 0;  }
}

void main()
{
fp = &Cls.foo;

Cls c = new Cls;
ptr = &c.k;  // <-- why always need a new instance?
}

As compared to delegate, is there no analogous way to specify this?

ptr = &Cls.k

Thanks!

In fact, this should fail to compile. The fact that it succeeds is a bug. You should enter it in bugzilla (is it already there?) Did you try running it? I get a segfault. fp is a member function, which means it needs a hidden 'this' pointer. When you assign &Cls.foo to fp, this should result in the same error as if you typed Cls.foo(): Error: need 'this' to access member foo -Steve

A direct, C++-style pointer-to-member-function is occasionally useful. (Though rarely, since delegates are more useful nearly every time.) Allowing this syntax is the only sensible way to get access to them. The resulting pointer can then manually be shoved into a delegate: void function() fp = &Cls.foo; Cls c = new Cls; void delegate() dg; dg.funcptr = fp; dg.ptr = c; // I forget if a cast to void* is necessary... dg(); Pyd relies on this behavior to implement its class wrapping, and it would be fairly inconvenient if it went away. -- Kirk McDonald http://kirkmcdonald.blogspot.com Pyd: Connecting D and Python http://pyd.dsource.org
Jul 29 2008
parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"Kirk McDonald" wrote
 Steven Schveighoffer wrote:
 "ws" wrote

Suppose i have the following:

int function() fp;
int *ptr;
class Cls
{
int k;
int foo()  {  return 0;  }
}

void main()
{
fp = &Cls.foo;

Cls c = new Cls;
ptr = &c.k;  // <-- why always need a new instance?
}

As compared to delegate, is there no analogous way to specify this?

ptr = &Cls.k

Thanks!

In fact, this should fail to compile. The fact that it succeeds is a bug. You should enter it in bugzilla (is it already there?) Did you try running it? I get a segfault. fp is a member function, which means it needs a hidden 'this' pointer. When you assign &Cls.foo to fp, this should result in the same error as if you typed Cls.foo(): Error: need 'this' to access member foo -Steve

A direct, C++-style pointer-to-member-function is occasionally useful. (Though rarely, since delegates are more useful nearly every time.) Allowing this syntax is the only sensible way to get access to them. The resulting pointer can then manually be shoved into a delegate: void function() fp = &Cls.foo; Cls c = new Cls; void delegate() dg; dg.funcptr = fp; dg.ptr = c; // I forget if a cast to void* is necessary... dg(); Pyd relies on this behavior to implement its class wrapping, and it would be fairly inconvenient if it went away.

I had no idea you could build delegates this way. But even still, the function signature is not correct, it should be something like: void function(Cls c) fp = &Cls.foo; But in any case, the original code seems like dangerous behavior to allow without casting. There should at least be a cast involved so the user is forced to say "yes, I know that the function signature isn't correct, do it anyways". I still say this should be a bug. -Steve
Jul 29 2008
parent Kirk McDonald <kirklin.mcdonald gmail.com> writes:
Steven Schveighoffer wrote:
 "Kirk McDonald" wrote
 
Steven Schveighoffer wrote:

"ws" wrote


Suppose i have the following:

int function() fp;
int *ptr;
class Cls
{
int k;
int foo()  {  return 0;  }
}

void main()
{
fp = &Cls.foo;

Cls c = new Cls;
ptr = &c.k;  // <-- why always need a new instance?
}

As compared to delegate, is there no analogous way to specify this?

ptr = &Cls.k

Thanks!

In fact, this should fail to compile. The fact that it succeeds is a bug. You should enter it in bugzilla (is it already there?) Did you try running it? I get a segfault. fp is a member function, which means it needs a hidden 'this' pointer. When you assign &Cls.foo to fp, this should result in the same error as if you typed Cls.foo(): Error: need 'this' to access member foo -Steve

A direct, C++-style pointer-to-member-function is occasionally useful. (Though rarely, since delegates are more useful nearly every time.) Allowing this syntax is the only sensible way to get access to them. The resulting pointer can then manually be shoved into a delegate: void function() fp = &Cls.foo; Cls c = new Cls; void delegate() dg; dg.funcptr = fp; dg.ptr = c; // I forget if a cast to void* is necessary... dg(); Pyd relies on this behavior to implement its class wrapping, and it would be fairly inconvenient if it went away.

I had no idea you could build delegates this way. But even still, the function signature is not correct, it should be something like: void function(Cls c) fp = &Cls.foo; But in any case, the original code seems like dangerous behavior to allow without casting. There should at least be a cast involved so the user is forced to say "yes, I know that the function signature isn't correct, do it anyways". I still say this should be a bug. -Steve

The only really correct (that is, type-safe) solution is to do something like what C++ does. The syntax for this is astoundingly ugly, but let me walk you through it. (This is C++ code, so brace yourself.) :-) class C { public: virtual void foo()=0; // an abstract ("pure virtual") method }; // Alias the pointer type. typedef void (C::* ptr_t)(); void f(C* c) { // Take the address of the method. ptr_t fn = &C::foo; // Call it on the instance. (c->*fn)(); } Several things deserve mention: 1) The syntax is just weird. Take this: typedef void (C::* ptr_t)(); That is aliasing the type "void (C::*)()" to the name ptr_t. That type is a function pointer type. It's like a void function() which can only apply to member functions of class C. C::* basically means "pointer to member of C." On the other side of the equation, we have: (c->*fn)(); This is binding the pointer-to-member "fn" to the instance pointed to by c, and then calling the result. In the example, it is basically equivalent to: c->foo(); ->* is an operator in its own right in C++. 2) It does a virtual call! Where a pointer-to-member-function is a regular function pointer in D, in C++ it is basically just the index of the function in the vtable. (Unless, of course, the member function isn't virtual.) As an aside, it is precisely the non-virtual nature of these pointers-to-member-functions that Pyd exploits. The details behind this chicanery are more involved than I want to describe here. 3) The pointers are type-safe. This bears mentioning again: Only member functions of class C (which have that particular signature) can be assigned to a variable of that ptr_t type above. This is exactly in line with what you were saying: void function() is not the correct type for the function pointer. As it is, pointers-to-member-functions are basically a half-feature in D. You can do it, but it arguably breaks the type system in weird ways. I would argue that this is fine, since they are innately ugly. -- Kirk McDonald http://kirkmcdonald.blogspot.com Pyd: Connecting D and Python http://pyd.dsource.org
Jul 30 2008