www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Template for function or delegate (nothing else)

reply useo <useo start.bg> writes:
Is it possible to create a template which only accepts functions or
delegates like this example:

class Example(T : void function()) { // or ..(T : void delegate())..

	T callback;

}

Where T is a function or a delegate...

Thanks for every suggestion!
Feb 09 2011
next sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Wed, 09 Feb 2011 14:35:42 -0500, useo <useo start.bg> wrote:

 Is it possible to create a template which only accepts functions or
 delegates like this example:

 class Example(T : void function()) { // or ..(T : void delegate())..

 	T callback;

 }

 Where T is a function or a delegate...

 Thanks for every suggestion!

class Example(T) if (is(T == delegate) || is(T == function)) { T callback; } -Steve
Feb 09 2011
next sibling parent useo <useo start.bg> writes:
== Auszug aus Steven Schveighoffer (schveiguy yahoo.com)'s Artikel
 On Wed, 09 Feb 2011 14:35:42 -0500, useo <useo start.bg> wrote:
 Is it possible to create a template which only accepts functions


 delegates like this example:

 class Example(T : void function()) { // or ..(T : void delegate


 	T callback;

 }

 Where T is a function or a delegate...

 Thanks for every suggestion!

{ T callback; } -Steve

Wow, works great - THANKS :)
Feb 09 2011
prev sibling next sibling parent reply useo <useo start.bg> writes:
== Auszug aus Steven Schveighoffer (schveiguy yahoo.com)'s Artikel
 On Wed, 09 Feb 2011 14:35:42 -0500, useo <useo start.bg> wrote:
 Is it possible to create a template which only accepts functions


 delegates like this example:

 class Example(T : void function()) { // or ..(T : void delegate


 	T callback;

 }

 Where T is a function or a delegate...

 Thanks for every suggestion!

{ T callback; } -Steve

Is there any chance to do the same for methods like: void example(T)() { } ... something like: void bindEvent(T)(if (is(T == delegate) || is(T == function)))()...
Feb 09 2011
next sibling parent bearophile <bearophileHUGS lycos.com> writes:
useo:

 ... something like:
 
 void bindEvent(T)(if (is(T == delegate) || is(T == function)))()...

void foo(T)(T x) if (is(T == delegate) || is(T == function)) { ... } Bye, bearophile
Feb 09 2011
prev sibling parent reply useo <useo start.bg> writes:
== Auszug aus Steven Schveighoffer (schveiguy yahoo.com)'s Artikel
 On Wed, 09 Feb 2011 14:59:33 -0500, useo <useo start.bg> wrote:
 == Auszug aus Steven Schveighoffer (schveiguy yahoo.com)'s Artikel
 On Wed, 09 Feb 2011 14:35:42 -0500, useo <useo start.bg> wrote:
 Is it possible to create a template which only accepts




 or
 delegates like this example:

 class Example(T : void function()) { // or ..(T : void delegate


 	T callback;

 }

 Where T is a function or a delegate...

 Thanks for every suggestion!

{ T callback; } -Steve

Is there any chance to do the same for methods like: void example(T)() { } ... something like: void bindEvent(T)(if (is(T == delegate) || is(T == function)))


 Yes, but you have the order mixed up.
 void bindEvent(T)() if (is...)
 In general form, a template constraint goes after the declaration,

 before the body of the template.
 -Steve

Ah, okay... I already tried the if-statement after the declaration but I always got an error like this: "... semicolon expected following function declaration" I just removed ( and ) from the if-statement and it's working, thanks in again!
Feb 09 2011
parent reply useo <useo start.bg> writes:
I just have a problem with my variables.

For example... my class/template just looks like:

class Example(T) if (is(T == delegate) || is(T == function))
{
   T callback;

   void setCallback(T cb) {
      callback = cb;
   }

}

This means that I need variables like Example!(void function())
myVariable. But is there any possibility to use variables like
Example myVariable? The template declaration only defines the type of
a callback and perhaps one method-declaration nothing else. I already
tried Example!(void*) because delegates and functions are void
pointers but I always get an error. I hope there is any way to do
this.
Feb 09 2011
next sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
useo:

 I just have a problem with my variables.
 
 For example... my class/template just looks like:
 
 class Example(T) if (is(T == delegate) || is(T == function))
 {
    T callback;
 
    void setCallback(T cb) {
       callback = cb;
    }
 
 }
 
 This means that I need variables like Example!(void function())
 myVariable. But is there any possibility to use variables like
 Example myVariable?

D is not the SML language, templates are just placeholders. If you don't instantiate a template, you have only a symbol. Example is only assignable to an alias (and in past, to a typedef): alias Example Foo;
 The template declaration only defines the type of
 a callback and perhaps one method-declaration nothing else. I already
 tried Example!(void*) because delegates and functions are void
 pointers but I always get an error. I hope there is any way to do
 this.

I don't yet understand what you are trying to do. Other notes: - What if your T is a functor (a callable class/struct/union instance that defined opCall)? - sizeof of a function pointer is 1 CPU word, while a delegate is 2 CPU words (and a delegate clojure has stuff on the heap too, sometimes). Bye, bearophile
Feb 09 2011
parent reply useo <useo start.bg> writes:
== Auszug aus bearophile (bearophileHUGS lycos.com)'s Artikel
 useo:
 I just have a problem with my variables.

 For example... my class/template just looks like:

 class Example(T) if (is(T == delegate) || is(T == function))
 {
    T callback;

    void setCallback(T cb) {
       callback = cb;
    }

 }

 This means that I need variables like Example!(void function


 myVariable. But is there any possibility to use variables like
 Example myVariable?


is only assignable to an alias (and in past, to a typedef):
 alias Example Foo;
 The template declaration only defines the type of
 a callback and perhaps one method-declaration nothing else. I


 tried Example!(void*) because delegates and functions are void
 pointers but I always get an error. I hope there is any way


 this.

Other notes: - What if your T is a functor (a callable class/struct/union

 - sizeof of a function pointer is 1 CPU word, while a delegate

sometimes).
 Bye,
 bearophile

Idea is the following: class Example(T) if (is(T == delegate) || is(T == function)) { T callback; void setCallback(T cb) { callback = cb; } void opCall() { callback(); } } other file: import example; private { Example variable; } void setExampleVariable(Example ex) { variable = ex; } void callCurrentExampleVariable() { variable(); }
Feb 09 2011
next sibling parent useo <useo start.bg> writes:
== Auszug aus Steven Schveighoffer (schveiguy yahoo.com)'s Artikel
 On Wed, 09 Feb 2011 16:41:25 -0500, useo <useo start.bg> wrote:
 == Auszug aus bearophile (bearophileHUGS lycos.com)'s Artikel
 useo:
 I just have a problem with my variables.

 For example... my class/template just looks like:

 class Example(T) if (is(T == delegate) || is(T ==




 {
    T callback;

    void setCallback(T cb) {
       callback = cb;
    }

 }

 This means that I need variables like Example!(void




 ())
 myVariable. But is there any possibility to use variables




 Example myVariable?




 you don't instantiate a template, you have only a symbol.


 is only assignable to an alias (and in past, to a typedef):
 alias Example Foo;
 The template declaration only defines the type of
 a callback and perhaps one method-declaration nothing




 already
 tried Example!(void*) because delegates and functions are




 pointers but I always get an error. I hope there is any way


 this.

Other notes: - What if your T is a functor (a callable class/struct/union

 - sizeof of a function pointer is 1 CPU word, while a



 is 2 CPU words (and a delegate clojure has stuff on the heap


 sometimes).
 Bye,
 bearophile

Idea is the following: class Example(T) if (is(T == delegate) || is(T == function)) { T callback; void setCallback(T cb) { callback = cb; } void opCall() { callback(); } } other file: import example; private { Example variable; } void setExampleVariable(Example ex) { variable = ex; } void callCurrentExampleVariable() { variable(); }


 struct is MUCH better suited for this):
 // untested!
 struct Example
 {
     private
     {
        bool isDelegate;
        union
        {
           void function() fn;
           void delegate() dg;
        }
     }
     void setCallback(void function() f) { this.fn = f;

     void setCallback(void delegate() d) { this.dg = d;

     void opCall()
     {
        if(isDelegate)
           dg();
        else
           fn();
     }
 }
 -Steve

Looks really interesting and seems to work. Thanks in advance!
Feb 09 2011
prev sibling parent reply useo <useo start.bg> writes:
I implemented all I wanted and it works perfectly ;).

But I'm using the "if (is(T == delegate) || is(T == function))"-
statement in another class/template.

class Example(T) if (is(T == delegate) || is(T == function)) {
...
}

Now, when I declare Example!(void function()) myVar; I always get:

Error: template instance Example!(void function()) does not match
template declaration Example(T) if (is(T == delegate) || is(T ==
function))
Error: Example!(void function()) is used as a type

When I declare myVar as Example!(function), I get some other errors.

What's wrong with my code?
Feb 10 2011
parent reply useo <useo start.bg> writes:
== Auszug aus Steven Schveighoffer (schveiguy yahoo.com)'s Artikel
 On Thu, 10 Feb 2011 09:09:03 -0500, useo <useo start.bg> wrote:
 I implemented all I wanted and it works perfectly ;).

 But I'm using the "if (is(T == delegate) || is(T == function))"-
 statement in another class/template.

 class Example(T) if (is(T == delegate) || is(T == function)) {
 ...
 }

 Now, when I declare Example!(void function()) myVar; I always get:

 Error: template instance Example!(void function()) does not match
 template declaration Example(T) if (is(T == delegate) || is(T ==
 function))
 Error: Example!(void function()) is used as a type

 When I declare myVar as Example!(function), I get some other


 What's wrong with my code?

message, it appears that your code is correct, but I'd have to play

 real example to be sure.
 -Steve

I created a complete, new file with the following code: module example; void main(string[] args) { Example!(void function()) myVar; } class Example(T) if (is(T == delegate) || is(T == function)) { } And what I get is: example.d(4): Error: template instance Example!(void function()) does not match template declaration Example(T) if (is(T == delegate) || is (T == function)) example.d(4): Error: Example!(void function()) is used as a type I'm using the current stable version 2.051.
Feb 10 2011
next sibling parent useo <useo start.bg> writes:
== Auszug aus useo (useo start.bg)'s Artikel
 == Auszug aus Steven Schveighoffer (schveiguy yahoo.com)'s Artikel
 On Thu, 10 Feb 2011 09:09:03 -0500, useo <useo start.bg> wrote:
 I implemented all I wanted and it works perfectly ;).

 But I'm using the "if (is(T == delegate) || is(T == function))"-
 statement in another class/template.

 class Example(T) if (is(T == delegate) || is(T == function)) {
 ...
 }

 Now, when I declare Example!(void function()) myVar; I always



 Error: template instance Example!(void function()) does not



 template declaration Example(T) if (is(T == delegate) || is(T ==
 function))
 Error: Example!(void function()) is used as a type

 When I declare myVar as Example!(function), I get some other


 What's wrong with my code?



 message, it appears that your code is correct, but I'd have to


 with a
 real example to be sure.
 -Steve

module example; void main(string[] args) { Example!(void function()) myVar; } class Example(T) if (is(T == delegate) || is(T == function)) { } And what I get is: example.d(4): Error: template instance Example!(void function())

 not match template declaration Example(T) if (is(T == delegate) ||

 (T == function))
 example.d(4): Error: Example!(void function()) is used as a type
 I'm using the current stable version 2.051.

I noticed, that this error only occurs when I use function as template-type. When I use Example!(void delegate()) myVar; it compiles without any error. With function - Example!(void function()) myVar; I get the error(s) above.
Feb 10 2011
prev sibling parent useo <useo start.bg> writes:
== Auszug aus Steven Schveighoffer (schveiguy yahoo.com)'s Artikel
 On Thu, 10 Feb 2011 09:48:14 -0500, useo <useo start.bg> wrote:
 I created a complete, new file with the following code:

 module example;

 void main(string[] args) {
 	Example!(void function()) myVar;
 }

 class Example(T) if (is(T == delegate) || is(T == function)) {
 }

 And what I get is:

 example.d(4): Error: template instance Example!(void function())


 not match template declaration Example(T) if (is(T == delegate)


 (T == function))
 example.d(4): Error: Example!(void function()) is used as a type

 I'm using the current stable version 2.051.

http://d.puremagic.com/issues/show_bug.cgi?id=3464 So use this instead: class Example(T) if (is(T == delegate) || is(typeof(*T.init) ==

 Ugly, I know, but I guess that's what we got to work with.
 -Steve

Yes, looks a bit unusual but it works, thanks!
Feb 10 2011
prev sibling parent useo <useo start.bg> writes:
== Auszug aus Steven Schveighoffer (schveiguy yahoo.com)'s Artikel
 On Wed, 09 Feb 2011 16:14:04 -0500, useo <useo start.bg> wrote:
 I just have a problem with my variables.

 For example... my class/template just looks like:

 class Example(T) if (is(T == delegate) || is(T == function))
 {
    T callback;

    void setCallback(T cb) {
       callback = cb;
    }

 }

 This means that I need variables like Example!(void function())
 myVariable. But is there any possibility to use variables like
 Example myVariable? The template declaration only defines the


 a callback and perhaps one method-declaration nothing else. I


 tried Example!(void*) because delegates and functions are void
 pointers but I always get an error. I hope there is any way to do
 this.


 when instantiating the template?  This is not possible, templates

 have all parameters defined at instantiation time.
 If you just want a shorter thing to type for Example!(void function

 you can do:
 alias Example!(void function()) MyType;
 MyType myVariable;
 -Steve

Yes, right, I don't want declare the template-type. Nevertheless... thanks
Feb 09 2011
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Wed, 09 Feb 2011 14:59:33 -0500, useo <useo start.bg> wrote:

 == Auszug aus Steven Schveighoffer (schveiguy yahoo.com)'s Artikel
 On Wed, 09 Feb 2011 14:35:42 -0500, useo <useo start.bg> wrote:
 Is it possible to create a template which only accepts functions


 delegates like this example:

 class Example(T : void function()) { // or ..(T : void delegate


 	T callback;

 }

 Where T is a function or a delegate...

 Thanks for every suggestion!

{ T callback; } -Steve

Is there any chance to do the same for methods like: void example(T)() { } ... something like: void bindEvent(T)(if (is(T == delegate) || is(T == function)))()...

Yes, but you have the order mixed up. void bindEvent(T)() if (is...) In general form, a template constraint goes after the declaration, but before the body of the template. -Steve
Feb 09 2011
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Wed, 09 Feb 2011 16:14:04 -0500, useo <useo start.bg> wrote:

 I just have a problem with my variables.

 For example... my class/template just looks like:

 class Example(T) if (is(T == delegate) || is(T == function))
 {
    T callback;

    void setCallback(T cb) {
       callback = cb;
    }

 }

 This means that I need variables like Example!(void function())
 myVariable. But is there any possibility to use variables like
 Example myVariable? The template declaration only defines the type of
 a callback and perhaps one method-declaration nothing else. I already
 tried Example!(void*) because delegates and functions are void
 pointers but I always get an error. I hope there is any way to do
 this.

If I understand you correctly, you don't want to declare the type of T when instantiating the template? This is not possible, templates must have all parameters defined at instantiation time. If you just want a shorter thing to type for Example!(void function()), you can do: alias Example!(void function()) MyType; MyType myVariable; -Steve
Feb 09 2011
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Wed, 09 Feb 2011 16:41:25 -0500, useo <useo start.bg> wrote:

 == Auszug aus bearophile (bearophileHUGS lycos.com)'s Artikel
 useo:
 I just have a problem with my variables.

 For example... my class/template just looks like:

 class Example(T) if (is(T == delegate) || is(T == function))
 {
    T callback;

    void setCallback(T cb) {
       callback = cb;
    }

 }

 This means that I need variables like Example!(void function


 myVariable. But is there any possibility to use variables like
 Example myVariable?


is only assignable to an alias (and in past, to a typedef):
 alias Example Foo;
 The template declaration only defines the type of
 a callback and perhaps one method-declaration nothing else. I


 tried Example!(void*) because delegates and functions are void
 pointers but I always get an error. I hope there is any way


 this.

Other notes: - What if your T is a functor (a callable class/struct/union

 - sizeof of a function pointer is 1 CPU word, while a delegate

sometimes).
 Bye,
 bearophile

Idea is the following: class Example(T) if (is(T == delegate) || is(T == function)) { T callback; void setCallback(T cb) { callback = cb; } void opCall() { callback(); } } other file: import example; private { Example variable; } void setExampleVariable(Example ex) { variable = ex; } void callCurrentExampleVariable() { variable(); }

I don't think you want templates. What you want is a tagged union (and a struct is MUCH better suited for this): // untested! struct Example { private { bool isDelegate; union { void function() fn; void delegate() dg; } } void setCallback(void function() f) { this.fn = f; isDelegate = false;} void setCallback(void delegate() d) { this.dg = d; isDelegate = true;} void opCall() { if(isDelegate) dg(); else fn(); } } -Steve
Feb 09 2011
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Thu, 10 Feb 2011 08:39:13 -0500, spir <denis.spir gmail.com> wrote:

 On 02/09/2011 11:05 PM, Steven Schveighoffer wrote:

 I don't think you want templates. What you want is a tagged union (and  
 a struct
 is MUCH better suited for this):

 // untested!

 struct Example
 {
 private
 {
 bool isDelegate;
 union
 {
 void function() fn;
 void delegate() dg;
 }
 }

 void setCallback(void function() f) { this.fn = f; isDelegate = false;}
 void setCallback(void delegate() d) { this.dg = d; isDelegate = true;}

 void opCall()
 {
 if(isDelegate)
 dg();
 else
 fn();
 }
 }

Waow, very nice solution. I really question the function/delegate distinction (mostly artificial, imo) that "invents" issues necessiting workarounds like that. What does it mean, what does it bring?

A function pointer is compatible with a C function pointer. C does not have delegates, so if you want to do callbacks, you need to use function pointers. There is no way to combine them and keep C compatibility.
 Right, there is one pointer less for funcs. This save 4 or 8 bytes, so  
 to say, nothing; who develops apps with arrays of billions of funcs?  
 There are written in source ;-) Even then, if this saving of apointer  
 was of any relevance, then it should be an implementation detail that  
 does not leak into artificial semantic diff, creating issues on the  
 programmer side. What do you think?

What you want is already implemented. There is a relatively new phobos construct that builds a delegate out of a function pointer. In fact, my code could use it and save the tag: // again, untested! import std.functional : toDelegate; struct Example { private void delegate() dg; void setCallback(void function() f) { this.dg = toDelegate(f); } void setCallback(void delegate() d) { this.dg = d; } void opCall() { dg(); } } Note that toDelegate doesn't appear on the docs because of a doc generation bug... -Steve
Feb 10 2011
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Thu, 10 Feb 2011 09:09:03 -0500, useo <useo start.bg> wrote:

 I implemented all I wanted and it works perfectly ;).

 But I'm using the "if (is(T == delegate) || is(T == function))"-
 statement in another class/template.

 class Example(T) if (is(T == delegate) || is(T == function)) {
 ...
 }

 Now, when I declare Example!(void function()) myVar; I always get:

 Error: template instance Example!(void function()) does not match
 template declaration Example(T) if (is(T == delegate) || is(T ==
 function))
 Error: Example!(void function()) is used as a type

 When I declare myVar as Example!(function), I get some other errors.

 What's wrong with my code?

Please post a full example that creates the error. From that error message, it appears that your code is correct, but I'd have to play with a real example to be sure. -Steve
Feb 10 2011
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Thu, 10 Feb 2011 09:48:14 -0500, useo <useo start.bg> wrote:


 I created a complete, new file with the following code:

 module example;

 void main(string[] args) {
 	Example!(void function()) myVar;
 }

 class Example(T) if (is(T == delegate) || is(T == function)) {
 }

 And what I get is:

 example.d(4): Error: template instance Example!(void function()) does
 not match template declaration Example(T) if (is(T == delegate) || is
 (T == function))
 example.d(4): Error: Example!(void function()) is used as a type

 I'm using the current stable version 2.051.

Found this invalid bug. Apparently, this is expected (!) behavior: http://d.puremagic.com/issues/show_bug.cgi?id=3464 So use this instead: class Example(T) if (is(T == delegate) || is(typeof(*T.init) == function)) Ugly, I know, but I guess that's what we got to work with. -Steve
Feb 10 2011
prev sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Thu, 10 Feb 2011 12:04:28 -0500, spir <denis.spir gmail.com> wrote:

 On 02/10/2011 02:51 PM, Steven Schveighoffer wrote:
 On Thu, 10 Feb 2011 08:39:13 -0500, spir <denis.spir gmail.com> wrote:

 On 02/09/2011 11:05 PM, Steven Schveighoffer wrote:

 I don't think you want templates. What you want is a tagged union  
 (and a struct
 is MUCH better suited for this):

 // untested!

 struct Example
 {
 private
 {
 bool isDelegate;
 union
 {
 void function() fn;
 void delegate() dg;
 }
 }

 void setCallback(void function() f) { this.fn = f; isDelegate =  
 false;}
 void setCallback(void delegate() d) { this.dg = d; isDelegate = true;}

 void opCall()
 {
 if(isDelegate)
 dg();
 else
 fn();
 }
 }

Waow, very nice solution. I really question the function/delegate distinction (mostly artificial, imo) that "invents" issues necessiting workarounds like that. What does it mean, what does it bring?

A function pointer is compatible with a C function pointer. C does not have delegates, so if you want to do callbacks, you need to use function pointers. There is no way to combine them and keep C compatibility.
 Right, there is one pointer less for funcs. This save 4 or 8 bytes, so  
 to
 say, nothing; who develops apps with arrays of billions of funcs?  
 There are
 written in source ;-) Even then, if this saving of apointer was of any
 relevance, then it should be an implementation detail that does not  
 leak into
 artificial semantic diff, creating issues on the programmer side. What  
 do you
 think?

What you want is already implemented. There is a relatively new phobos construct that builds a delegate out of a function pointer. In fact, my code could use it and save the tag: // again, untested! import std.functional : toDelegate; struct Example { private void delegate() dg; void setCallback(void function() f) { this.dg = toDelegate(f); } void setCallback(void delegate() d) { this.dg = d; } void opCall() { dg(); } } Note that toDelegate doesn't appear on the docs because of a doc generation bug...

Right. I had not thought at the C-compatibility issue. So, let us say the func/dg distinction must remain in the language, on programmer-side, because of that. Then, is there anything that prevent the above cast to be implicit? Then, programmers would only have to define a single interface, using delegate everywhere; and not care about where and how user funcs are defined. (because as you know presently whether a ref'ed func becomes a func pointer or a delegate depends on /where/ it is defined...) Second point. I would like referencing of functions/delegates passed as arguments to be implicite. After all, conceptually, what we pass is a "function object". Not a pointer. That the implementation needs to "point" them is just this, implementation. The '&' just pollutes the code meaninglessly;

This is the way it is in C, and D purposely does not do this to avoid ambiguity (did you want to call the function or get it's address?).
 and it's absence creates weird bugs:

 void f0 (     ) { writeln(1); }
 void f1 (int i) { writeln(i); }
 void do0 (void function (   ) f) { f( ); }
 void do1 (void function (int) f) { f(3); }

 unittest {
      // Error: function __trials__.do0 (void function() f) is not  
 callable
      // using argument types (void)
      do0(f0);

      // __trials__.d(46): Error: function __trials__.f1 (int i) is not  
 callable
      // using argument types ()
      do1(f1);

      do0(&f0);   // ok
      do1(&f1);   // ok
 }

 Error messages are difficult to interpret for a diagnosis, I guess. Note  
 that the first one concerns the caller, while the second one concerns  
 the callee...
 Implicite referencing would solve that issue /and/ match semantics /and/  
 be more consistent /and/ make code nicer. About consistency, I mean that  
 functions are already implicitely dereferenced: do1 does not need to  
 call its arg f using
 	(*f)(3);
 (this version works as well, indeed)

When properties are properly implemented, I expect this error message to be different. Currently, it thinks you are trying to call the function f0 and pass its result to do0. -Steve
Feb 10 2011
prev sibling next sibling parent spir <denis.spir gmail.com> writes:
On 02/09/2011 11:05 PM, Steven Schveighoffer wrote:
 On Wed, 09 Feb 2011 16:41:25 -0500, useo <useo start.bg> wrote:

 == Auszug aus bearophile (bearophileHUGS lycos.com)'s Artikel
 useo:
 I just have a problem with my variables.

 For example... my class/template just looks like:

 class Example(T) if (is(T == delegate) || is(T == function))
 {
 T callback;

 void setCallback(T cb) {
 callback = cb;
 }

 }

 This means that I need variables like Example!(void function


 myVariable. But is there any possibility to use variables like
 Example myVariable?


is only assignable to an alias (and in past, to a typedef):
 alias Example Foo;
 The template declaration only defines the type of
 a callback and perhaps one method-declaration nothing else. I


 tried Example!(void*) because delegates and functions are void
 pointers but I always get an error. I hope there is any way


 this.

Other notes: - What if your T is a functor (a callable class/struct/union

 - sizeof of a function pointer is 1 CPU word, while a delegate

sometimes).
 Bye,
 bearophile

Idea is the following: class Example(T) if (is(T == delegate) || is(T == function)) { T callback; void setCallback(T cb) { callback = cb; } void opCall() { callback(); } } other file: import example; private { Example variable; } void setExampleVariable(Example ex) { variable = ex; } void callCurrentExampleVariable() { variable(); }

I don't think you want templates. What you want is a tagged union (and a struct is MUCH better suited for this): // untested! struct Example { private { bool isDelegate; union { void function() fn; void delegate() dg; } } void setCallback(void function() f) { this.fn = f; isDelegate = false;} void setCallback(void delegate() d) { this.dg = d; isDelegate = true;} void opCall() { if(isDelegate) dg(); else fn(); } }

Waow, very nice solution. I really question the function/delegate distinction (mostly artificial, imo) that "invents" issues necessiting workarounds like that. What does it mean, what does it bring? Right, there is one pointer less for funcs. This save 4 or 8 bytes, so to say, nothing; who develops apps with arrays of billions of funcs? There are written in source ;-) Even then, if this saving of apointer was of any relevance, then it should be an implementation detail that does not leak into artificial semantic diff, creating issues on the programmer side. What do you think? Denis -- _________________ vita es estrany spir.wikidot.com
Feb 10 2011
prev sibling parent spir <denis.spir gmail.com> writes:
On 02/10/2011 02:51 PM, Steven Schveighoffer wrote:
 On Thu, 10 Feb 2011 08:39:13 -0500, spir <denis.spir gmail.com> wrote:

 On 02/09/2011 11:05 PM, Steven Schveighoffer wrote:

 I don't think you want templates. What you want is a tagged union (and a struct
 is MUCH better suited for this):

 // untested!

 struct Example
 {
 private
 {
 bool isDelegate;
 union
 {
 void function() fn;
 void delegate() dg;
 }
 }

 void setCallback(void function() f) { this.fn = f; isDelegate = false;}
 void setCallback(void delegate() d) { this.dg = d; isDelegate = true;}

 void opCall()
 {
 if(isDelegate)
 dg();
 else
 fn();
 }
 }

Waow, very nice solution. I really question the function/delegate distinction (mostly artificial, imo) that "invents" issues necessiting workarounds like that. What does it mean, what does it bring?

A function pointer is compatible with a C function pointer. C does not have delegates, so if you want to do callbacks, you need to use function pointers. There is no way to combine them and keep C compatibility.
 Right, there is one pointer less for funcs. This save 4 or 8 bytes, so to
 say, nothing; who develops apps with arrays of billions of funcs? There are
 written in source ;-) Even then, if this saving of apointer was of any
 relevance, then it should be an implementation detail that does not leak into
 artificial semantic diff, creating issues on the programmer side. What do you
 think?

What you want is already implemented. There is a relatively new phobos construct that builds a delegate out of a function pointer. In fact, my code could use it and save the tag: // again, untested! import std.functional : toDelegate; struct Example { private void delegate() dg; void setCallback(void function() f) { this.dg = toDelegate(f); } void setCallback(void delegate() d) { this.dg = d; } void opCall() { dg(); } } Note that toDelegate doesn't appear on the docs because of a doc generation bug...

Right. I had not thought at the C-compatibility issue. So, let us say the func/dg distinction must remain in the language, on programmer-side, because of that. Then, is there anything that prevent the above cast to be implicit? Then, programmers would only have to define a single interface, using delegate everywhere; and not care about where and how user funcs are defined. (because as you know presently whether a ref'ed func becomes a func pointer or a delegate depends on /where/ it is defined...) Second point. I would like referencing of functions/delegates passed as arguments to be implicite. After all, conceptually, what we pass is a "function object". Not a pointer. That the implementation needs to "point" them is just this, implementation. The '&' just pollutes the code meaninglessly; and it's absence creates weird bugs: void f0 ( ) { writeln(1); } void f1 (int i) { writeln(i); } void do0 (void function ( ) f) { f( ); } void do1 (void function (int) f) { f(3); } unittest { // Error: function __trials__.do0 (void function() f) is not callable // using argument types (void) do0(f0); // __trials__.d(46): Error: function __trials__.f1 (int i) is not callable // using argument types () do1(f1); do0(&f0); // ok do1(&f1); // ok } Error messages are difficult to interpret for a diagnosis, I guess. Note that the first one concerns the caller, while the second one concerns the callee... Implicite referencing would solve that issue /and/ match semantics /and/ be more consistent /and/ make code nicer. About consistency, I mean that functions are already implicitely dereferenced: do1 does not need to call its arg f using (*f)(3); (this version works as well, indeed) denis -- _________________ vita es estrany spir.wikidot.com
Feb 10 2011