www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Problem with delegates

reply Zarathustra <adam.chrapkowski gmail.com> writes:
Acces violation when I try use delegate function.

module test;

private{ 
  // tango.io
  import tango.io.Stdout;
}

// class Drawable  << super class >>
//______________________________________________________________
private abstract class 
Drawable{
	
  // fields
  protected const real delegate() m_Cmp;
	
  // overloaded operators
  public int
  opCmp(Object o){
    assert(m_Cmp, "Drawable.m_Cmp can not be null!");
    return cast(int)(this.m_Cmp() - (cast(typeof(this))o).m_Cmp());
  }
	
  // ctors
  public 
  this(real delegate() o_Cmp){
    m_Cmp = o_Cmp;
  }
}

// class Point  << child class >>
//______________________________________________________________
public final class 
Point : Drawable{
	
  // fields
  private double x;
  private double y;
  private double z;
	
  // features
  public void 
  Writefln(){
    Stdout.format("x: {}, y: {}, z: {}", x, y, z).newline();
  }
	
  // ctors
  this(uint o_x, uint o_y, uint o_z){
    super( delegate{ return cast(real)this.z; } );
    this.x = o_x;
    this.y = o_y;
    this.z = o_z;
  }
}

public void 
main(){
	try{
		Point [] l_point_arr;
		
		l_point_arr ~= new Point(0, 1, 2);
		l_point_arr ~= new Point(0, 1, 1);
		l_point_arr ~= new Point(0, 1, 4);
		l_point_arr ~= new Point(0, 1, 5);
		
		foreach(l_point; l_point_arr){
			l_point.Writefln();
		}
		
		Stdout.newline();
		l_point_arr.sort; // use opCmp property
		
		foreach(l_point; l_point_arr){
			l_point.Writefln();
		}
	}
	catch(Object o){
		Stdout.format("Fatal Error: {}", o.toString).newline();
	}
}

#output
x: 0.00, y: 1.00, z: 2.00
x: 0.00, y: 1.00, z: 1.00
x: 0.00, y: 1.00, z: 4.00
x: 0.00, y: 1.00, z: 5.00

Fatal Error: Access Violation
Sep 07 2008
parent reply Frank Benoit <keinfarbton googlemail.com> writes:
I haven't tried this, but i think it can work like this:
// in Point
   // ctors
   this(uint o_x, uint o_y, uint o_z){
     super( &comparator );
     this.x = o_x;
     this.y = o_y;
     this.z = o_z;
   }
   real comparator(){ return cast(real)this.z; }


Zarathustra schrieb:
 Acces violation when I try use delegate function.
 
 module test;
 
 private{ 
   // tango.io
   import tango.io.Stdout;
 }
 
 // class Drawable  << super class >>
 //______________________________________________________________
 private abstract class 
 Drawable{
 	
   // fields
   protected const real delegate() m_Cmp;
 	
   // overloaded operators
   public int
   opCmp(Object o){
     assert(m_Cmp, "Drawable.m_Cmp can not be null!");
     return cast(int)(this.m_Cmp() - (cast(typeof(this))o).m_Cmp());
   }
 	
   // ctors
   public 
   this(real delegate() o_Cmp){
     m_Cmp = o_Cmp;
   }
 }
 
 // class Point  << child class >>
 //______________________________________________________________
 public final class 
 Point : Drawable{
 	
   // fields
   private double x;
   private double y;
   private double z;
 	
   // features
   public void 
   Writefln(){
     Stdout.format("x: {}, y: {}, z: {}", x, y, z).newline();
   }
 	
   // ctors
   this(uint o_x, uint o_y, uint o_z){
     super( delegate{ return cast(real)this.z; } );
     this.x = o_x;
     this.y = o_y;
     this.z = o_z;
   }
 }
 
 public void 
 main(){
 	try{
 		Point [] l_point_arr;
 		
 		l_point_arr ~= new Point(0, 1, 2);
 		l_point_arr ~= new Point(0, 1, 1);
 		l_point_arr ~= new Point(0, 1, 4);
 		l_point_arr ~= new Point(0, 1, 5);
 		
 		foreach(l_point; l_point_arr){
 			l_point.Writefln();
 		}
 		
 		Stdout.newline();
 		l_point_arr.sort; // use opCmp property
 		
 		foreach(l_point; l_point_arr){
 			l_point.Writefln();
 		}
 	}
 	catch(Object o){
 		Stdout.format("Fatal Error: {}", o.toString).newline();
 	}
 }
 
 #output
 x: 0.00, y: 1.00, z: 2.00
 x: 0.00, y: 1.00, z: 1.00
 x: 0.00, y: 1.00, z: 4.00
 x: 0.00, y: 1.00, z: 5.00
 
 Fatal Error: Access Violation
Sep 07 2008
parent reply Zarathustra <adam.chrapkowski gmail.com> writes:
I know it works with additional function like 'Comparator'.
Probably when I try use anonymous delegate it have not acces to this, because
body of anonymous delegate must be nested inside for example constructor.

private class
Drawable{
  abstract real Comparator();
  [...]
}
public class
Point{
  [...]
  Comparator(){ return this.z; }
  [...]
}

Maybe I will find out another way to do this.


Frank Benoit Wrote:

 I haven't tried this, but i think it can work like this:
 // in Point
    // ctors
    this(uint o_x, uint o_y, uint o_z){
      super( &comparator );
      this.x = o_x;
      this.y = o_y;
      this.z = o_z;
    }
    real comparator(){ return cast(real)this.z; }
 
Sep 07 2008
parent reply Frank Benoit <keinfarbton googlemail.com> writes:
Zarathustra schrieb:
 I know it works with additional function like 'Comparator'.
 Probably when I try use anonymous delegate it have not acces to this, because
body of anonymous delegate must be nested inside for example constructor.
 
 private class
 Drawable{
   abstract real Comparator();
   [...]
 }
 public class
 Point{
   [...]
   Comparator(){ return this.z; }
   [...]
 }
 
 Maybe I will find out another way to do this.
 
 
 Frank Benoit Wrote:
 
 I haven't tried this, but i think it can work like this:
 // in Point
    // ctors
    this(uint o_x, uint o_y, uint o_z){
      super( &comparator );
      this.x = o_x;
      this.y = o_y;
      this.z = o_z;
    }
    real comparator(){ return cast(real)this.z; }
I think this is a D1-only problem. An nested function has always a reference to the current stack frame and navigates relative to it. In your case the stack frame of the ctor. If the ctor is completed, the stackframe gets invalid and a later call to the nested function fails. In D2, taking the address of the nested function would force the stack frame to be allocated on the heap and the later call would not make problems.
Sep 07 2008
parent Zarathustra <adam.chrapkowski gmail.com> writes:
Ok, thanks for information. Sorry, currently the Tango is not compatible with
D2. At least I do not know anything about it. But I hope D2 will be more and
more popular and the number of libraries which support it will be grow.

Best regards
Zarathustra

Frank Benoit Wrote:

 I think this is a D1-only problem. An nested function has always a
 reference to the current stack frame and navigates relative to it. In
 your case the stack frame of the ctor. If the ctor is completed, the
 stackframe gets invalid and a later call to the nested function fails.
 
 In D2, taking the address of the nested function would force the stack
 frame to be allocated on the heap and the later call would not make
 problems.
 
Sep 07 2008