www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Can't pass delegate to template

reply Kramer <Kramer_member pathlink.com> writes:
I'm trying to pass a delegate to a template but keep getting the error saying
the template instance doesn't match any template declaration.  Has anyone tried
this and been successful?  I've looked at the doc and it just says that
templates accept type, value and alias type parameters; it doesn't explicitly
exclude delegates though.  Is this something that's going to be supported?

Here's an example:

# import std.stdio;
#
# void main()
# {
#     int delegate() dg;
#     int foo() { return 3; }
#    
#     dg = &foo;
#     test!(dg);
# }
#
# template test(T)
# {
#     void test(T dg)
#     {
#         int i = dg();
#         writef("i = %d\n", i);
#     }
# }

Compiling the above gives: TemplateTest.d(9): template instance test!(dg) does
not match any template declaration

I've also tried specializing it, but still to no avail. :(

Using DMD 0.111.

-Kramer
Feb 09 2005
parent reply Niall FitzGibbon <billdoor gmail.com> writes:
Kramer wrote:
 I'm trying to pass a delegate to a template but keep getting the error saying
 the template instance doesn't match any template declaration.  Has anyone tried
 this and been successful?  I've looked at the doc and it just says that
 templates accept type, value and alias type parameters; it doesn't explicitly
 exclude delegates though.  Is this something that's going to be supported?
 
 Here's an example:
 
 # import std.stdio;
 #
 # void main()
 # {
 #     int delegate() dg;
 #     int foo() { return 3; }
 #    
 #     dg = &foo;
 #     test!(dg);
 # }
 #
 # template test(T)
 # {
 #     void test(T dg)
 #     {
 #         int i = dg();
 #         writef("i = %d\n", i);
 #     }
 # }

It seems that the template itself is expecting a type parameter but you're trying to instantiate it with the instance of the delegate itself. As I understand it, test!(int delegate()) would be the correct form to instantiate that template. Maybe I'm missing something -- is D supposed to choose a type parameter from the type of a variable used in the instantiation? I don't remember reading anything to that effect in the D spec, but it might be a neat feature, if possible.
Feb 10 2005
next sibling parent reply Stewart Gordon <smjg_1998 yahoo.com> writes:
Niall FitzGibbon wrote:
<snip>
 It seems that the template itself is expecting a type parameter but 
 you're trying to instantiate it with the instance of the delegate itself.
 As I understand it, test!(int delegate()) would be the correct form to 
 instantiate that template.

Correct.
 Maybe I'm missing something -- is D supposed to choose a type parameter 
 from the type of a variable used in the instantiation?

No. And even if it did, it would probably not be by the OP's syntax. Stewart. -- My e-mail is valid but not my primary mailbox. Please keep replies on the 'group where everyone may benefit.
Feb 10 2005
parent reply Kramer <Kramer_member pathlink.com> writes:
Compiles, but doesn't print.  Maybe it's half-way supported at the moment?

-Kramer

In article <cufhh6$1pg8$1 digitaldaemon.com>, Stewart Gordon says...
Niall FitzGibbon wrote:
<snip>
 It seems that the template itself is expecting a type parameter but 
 you're trying to instantiate it with the instance of the delegate itself.
 As I understand it, test!(int delegate()) would be the correct form to 
 instantiate that template.

Correct.
 Maybe I'm missing something -- is D supposed to choose a type parameter 
 from the type of a variable used in the instantiation?

No. And even if it did, it would probably not be by the OP's syntax. Stewart. -- My e-mail is valid but not my primary mailbox. Please keep replies on the 'group where everyone may benefit.

Feb 10 2005
parent reply Niall FitzGibbon <billdoor gmail.com> writes:
Kramer wrote:
 Compiles, but doesn't print.  Maybe it's half-way supported at the moment?
 
 -Kramer

You have to actually call the function that's part of the template. My first guess at this was to do: test!(int delegate()).test(dg); or test!(typeof(dg)).test(dg); as Ben suggested. However, this lead to a compile error. I managed to get it to compile by changing the function name to be different to the template name. I'm not sure if this is a bug or intentional on the compiler's part, but renaming the function or template to be different from the other works: test!(typeof(dg)).testb(dg); template test(T) { void testb(T dg) { int i = dg(); writef("i = %d\n", i); } }
Feb 10 2005
parent reply Stewart Gordon <smjg_1998 yahoo.com> writes:
Niall FitzGibbon wrote:
 Kramer wrote:
 
 Compiles, but doesn't print.  Maybe it's half-way supported at the 
 moment?

You have to actually call the function that's part of the template.

You mean test!(int delegate()); compiles? That would seem a bug - I thought such blatant nop statements were meant to be illegal in D.
 My first guess at this was to do:
 
 test!(int delegate()).test(dg);
 
 or
 
 test!(typeof(dg)).test(dg);
 
 as Ben suggested.

My first guess would be test!(int delegate())(dg); or test!(typeof(dg))(dg);
 However, this lead to a compile error. I managed to get it to compile by 
 changing the function name to be different to the template name.

That suggests that when the only member of a template has the same name as the template itself, the only-name-once notation _must_ be used. Maybe this is to void ambiguities.... Stewart. -- My e-mail is valid but not my primary mailbox. Please keep replies on the 'group where everyone may benefit.
Feb 10 2005
parent Niall FitzGibbon <billdoor gmail.com> writes:
 That suggests that when the only member of a template has the same name 
 as the template itself, the only-name-once notation _must_ be used. 
 Maybe this is to void ambiguities....
 
 Stewart.
 

That seems logical. I wasn't aware that the test!(typeof(dg))(dg) format would work -- I was going by the TCopy/copy example in the template documentation :)
Feb 10 2005
prev sibling parent reply Ben Hinkle <Ben_member pathlink.com> writes:
In article <cufg4o$1nsi$1 digitaldaemon.com>, Niall FitzGibbon says...
Kramer wrote:
 I'm trying to pass a delegate to a template but keep getting the error saying
 the template instance doesn't match any template declaration.  Has anyone tried
 this and been successful?  I've looked at the doc and it just says that
 templates accept type, value and alias type parameters; it doesn't explicitly
 exclude delegates though.  Is this something that's going to be supported?
 
 Here's an example:
 
 # import std.stdio;
 #
 # void main()
 # {
 #     int delegate() dg;
 #     int foo() { return 3; }
 #    
 #     dg = &foo;
 #     test!(dg);
 # }
 #
 # template test(T)
 # {
 #     void test(T dg)
 #     {
 #         int i = dg();
 #         writef("i = %d\n", i);
 #     }
 # }

It seems that the template itself is expecting a type parameter but you're trying to instantiate it with the instance of the delegate itself. As I understand it, test!(int delegate()) would be the correct form to instantiate that template. Maybe I'm missing something -- is D supposed to choose a type parameter from the type of a variable used in the instantiation? I don't remember reading anything to that effect in the D spec, but it might be a neat feature, if possible.

test!(typeof(dg))
Feb 10 2005
parent reply Kramer <Kramer_member pathlink.com> writes:
In article <cufl90$1u3k$1 digitaldaemon.com>, Ben Hinkle says...
In article <cufg4o$1nsi$1 digitaldaemon.com>, Niall FitzGibbon says...
Kramer wrote:
 I'm trying to pass a delegate to a template but keep getting the error saying
 the template instance doesn't match any template declaration.  Has anyone tried
 this and been successful?  I've looked at the doc and it just says that
 templates accept type, value and alias type parameters; it doesn't explicitly
 exclude delegates though.  Is this something that's going to be supported?
 
 Here's an example:
 
 # import std.stdio;
 #
 # void main()
 # {
 #     int delegate() dg;
 #     int foo() { return 3; }
 #    
 #     dg = &foo;
 #     test!(dg);
 # }
 #
 # template test(T)
 # {
 #     void test(T dg)
 #     {
 #         int i = dg();
 #         writef("i = %d\n", i);
 #     }
 # }

It seems that the template itself is expecting a type parameter but you're trying to instantiate it with the instance of the delegate itself. As I understand it, test!(int delegate()) would be the correct form to instantiate that template. Maybe I'm missing something -- is D supposed to choose a type parameter from the type of a variable used in the instantiation? I don't remember reading anything to that effect in the D spec, but it might be a neat feature, if possible.

test!(typeof(dg))

This compiles, but when run doesn't print anything. Plus, I just realized, I'd like to be able to templatize variable "i" with the return type of the template. I think I might be asking for too much... -Kramer
Feb 10 2005
parent reply "Ben Hinkle" <bhinkle mathworks.com> writes:
test!(typeof(dg))

This compiles, but when run doesn't print anything. Plus, I just realized, I'd like to be able to templatize variable "i" with the return type of the template. I think I might be asking for too much...

To call the function you need to explicitly call it: test!(typeof(dg))(dg); What's going on is the test!(typeof(dg)) just "instantiates" the template and doesn't do anything else. I'm exactly sure why you are using a template, though. You might want to consider using overloaded test functions: import std.stdio; void main() { int foo() { return 3; } test(&foo); } void test(int delegate() dg) { int i = dg(); writef("i = %d\n", i); } void test(double delegate() dg) { double x = dg(); writef("x = %g\n", x); }
Feb 10 2005
parent reply Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
Ben Hinkle wrote:
 I'm exactly sure why you are using a template, though. You might want to 
 consider using overloaded test functions:

Or here is an, IMHO, prettier template: import std.stdio; void main() { int foo() { return 3; } test!(int)(&foo); } template test(T) void test(T delegate() dg) { writefln("i = ", dg()); }
Feb 10 2005
parent Kramer <Kramer_member pathlink.com> writes:
In article <cug9kk$2lkf$1 digitaldaemon.com>, Russ Lewis says...
Ben Hinkle wrote:
 I'm exactly sure why you are using a template, though. You might want to 
 consider using overloaded test functions:

Or here is an, IMHO, prettier template: import std.stdio; void main() { int foo() { return 3; } test!(int)(&foo); } template test(T) void test(T delegate() dg) { writefln("i = ", dg()); }

This works great, thanks (and everyone else's examples)! I get excited with some of D's features and don't always think them through before attempting use; that happens less though the more D I use. I really like this language and hope for D's success. :) Anyway, I do think it would be nice if you were able to extract the return type of a delegate/function. I.e.: test!(typeof(foo.return))(&foo) // something akin to this (or even going further, be able to extract a non-variadic functions parm types which could be resolved at compile-time) I just like genericity in general. I think it makes for more flexible programming IMO. -Kramer
Feb 10 2005