Thread overview
Problem with delegates
Sep 07, 2008
Zarathustra
Sep 07, 2008
Frank Benoit
Sep 07, 2008
Zarathustra
Sep 07, 2008
Frank Benoit
Sep 07, 2008
Zarathustra
September 07, 2008
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
September 07, 2008
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
September 07, 2008
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; }
> 

September 07, 2008
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.

September 07, 2008
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.
>